shell實(shí)現(xiàn)貪吃蛇的示例代碼
前言
這是幾年前剛接觸shell,用bash shell寫(xiě)的一個(gè)貪吃蛇。剛才看見(jiàn)了,試了一下之前寫(xiě)的代碼,在mac os上效果不在理想,放到linux服務(wù)器,看起來(lái)運(yùn)行著還行。
給大家再分享一下。
下面是我當(dāng)時(shí)發(fā)的時(shí)候?qū)懙谋尘靶畔?,我就不改了,直接粘過(guò)來(lái)了。
背景
最近想系統(tǒng)看下base shell的基本語(yǔ)法知識(shí),可是看了這些if else之后還是不知道做什么就想到寫(xiě)了個(gè)貪吃蛇,我還以為我是第一個(gè)想到用shell寫(xiě)貪吃蛇的呢,可是后來(lái)看到已經(jīng)有人寫(xiě)過(guò)了,不過(guò)我也是懶的看別人代碼的人,所以就用自己的思路實(shí)現(xiàn)了下,熟練下這些基本的shell語(yǔ)法。
寫(xiě)這個(gè)重點(diǎn)是想練習(xí)下shell語(yǔ)法,所以貪吃蛇的實(shí)現(xiàn)算法倒不是重點(diǎn),況且以前大學(xué)的時(shí)候各類(lèi)小游戲用什么語(yǔ)言都寫(xiě)過(guò),這些小算法如果不考慮性能確實(shí)沒(méi)什么意思。
當(dāng)然了貪吃蛇最好用的數(shù)據(jù)結(jié)構(gòu)自然是stack,可是我真的不想花時(shí)間考慮用shell實(shí)現(xiàn)一個(gè)棧,所以就用一個(gè)靜態(tài)的一維數(shù)組和一個(gè)動(dòng)態(tài)的一維數(shù)組實(shí)現(xiàn)的(shell中的數(shù)組本來(lái)就是動(dòng)態(tài)的,我這樣說(shuō)只是說(shuō)我的實(shí)現(xiàn)的效果是這樣)。
環(huán)境
win10內(nèi)嵌的Linux beta版本(ubuntu14.0)帶的bash
如果有小伙伴復(fù)制下面代碼跑不動(dòng),請(qǐng)考慮下運(yùn)行環(huán)境。
源碼
下面的中文注釋是剛才添加的,用的這個(gè)bash是不支持中文的,我的英文真的比較爛,所以剛才把中文注釋加了下
玩的時(shí)候使用上下左右鍵就行(本想用hjkl這四鍵控制上下左右的,覺(jué)得不太習(xí)慣)
主要思路就是:貪吃蛇運(yùn)行界面使用一個(gè)后臺(tái)進(jìn)程,用另一個(gè)進(jìn)程來(lái)監(jiān)聽(tīng)輸入(我最初的想法是一個(gè)shell進(jìn)程就行,在貪吃蛇運(yùn)行中的等待時(shí)間來(lái)監(jiān)聽(tīng)輸入,后來(lái)發(fā)現(xiàn)還有這種玩法,我就改用這種實(shí)現(xiàn),通過(guò)傳遞一個(gè)信號(hào)來(lái)處理)
#! /bin/bash
#下面是游戲界面的寬和高
# the width
with=42
# the height
height=22
#這個(gè)是游戲運(yùn)行區(qū)域
# area
area=(
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9
)
#bool
false=0
true=1
#貪吃蛇的一些信息
#snake info
head=47
tail=45
originPos=(45 46 47)
snakeBody=2
snakeFood=3
curPos=(${originPos[*]})
#game logic val
speed=0.2
foodPos=50
left=2
right=-2
up=3
down=-3
moveDirection=$right
eat=$true
#game info
side=$$
main=$!
#這個(gè)是開(kāi)始時(shí)的界面
#start show interface
function startShowInterface()
{
seconds=$1
printf "\e[1;42m"
printf "******************************************\n"
for ((i=0; i<10; i++))
do
printf "* *\n"
done
printf "*******\e[1;31msnake start after: $seconds seconds\e[0m\e[1;42m*******\n"
for ((i=0; i<10; i++))
do
printf "* *\n"
done
printf "******************************************\n"
printf "\e[0m"
}
#start show
function startShow()
{
seconds=1;
while [[ $seconds -gt -1 ]];
do
clear;
startShowInterface $seconds;
sleep 1;
let seconds--;
done
}
startShow;
#這個(gè)是游戲顯示界面
# game main inteface
function gameMainInterface
{
clear;
pos=0
echo -e "\e[1;42m"
for data in ${area[@]};
do
case $data in
[9])
printf "\n"
;;
[1])
printf "#"
;;
[0])
printf " "
;;
[$snakeBody])
printf "\e[1;31m"
if [[ $pos = $head ]]; then
printf "@"
else
printf "*"
fi
printf "\e[0m\e[1;42m"
;;
[$snakeFood])
printf "\e[1;34m&\e[0m\e[1;42m"
;;
esac
let pos++
done
echo -e "\e[0m"
}
#initinal snake body and pos
function initSnake()
{
for data in ${originPos[@]};
do
area[$data]=$snakeBody
done
}
initSnake;
#繪制貪吃蛇
#draw snake
function drawSnake()
{
for data in ${originPos[@]};
do
area[$data]=0
done
for data in ${curPos[@]};
do
area[$data]=$snakeBody
done
}
#隨機(jī)生成食物位置
#generate food
function generateFood()
{
if [[ $eat = $false ]]; then
return
fi
done=$false
while [[ $done = $false ]];
do
newFoodPos=$(( RANDOM%$(( $(( $with-1 ))*$(( $height-1 )) )) ))
[[ ${area[$newFoodPos]} = 0 ]] && area[$foodPos]=0 && foodPos=$newFoodPos && (( area[$foodPos]=$snakeFood )) && done=$true && eat=$false
done
}
#貪吃蛇移動(dòng)的算法,用的一維數(shù)組,我也就這樣來(lái)實(shí)現(xiàn)了
#move
function snakeMove()
{
originPos=(${curPos[*]})
length=${#curPos[*]}
head=${curPos[$(( $length-1 ))]}
case $moveDirection in
$left)
let head--
[[ $(( $(( $head-2 ))%$with )) -eq 0 ]] && kill -35 $side
;;
$right)
let head++
[[ $(( $head%$with )) -eq 0 ]] && kill -35 $side
;;
$up)
let head=head-with
let head--
[[ $head -lt $with ]] && kill -35 $side
;;
$down)
let head=head+with
let head++
[[ $head -gt $(( $with*$(( $height-1 )) )) ]] && kill -35 $side
;;
esac
if [[ $head -eq $foodPos ]]; then
curPos[length]=$head
eat=$true
else
for ((i=0; i<$((length-1)); i++));
do
curPos[i]=${curPos[$((i+1))]}
done
curPos[$((length-1))]=$head
fi
}
#游戲運(yùn)行的進(jìn)程,游戲主邏輯都在這里了
#main interface
function mainInterface
{
trap "moveDirection=$left" 36
trap "moveDirection=$right" 37
trap "moveDirection=$up" 38
trap "moveDirection=$down" 39
run=$true
while [[ $run -eq $true ]];
do
generateFood;
snakeMove;
drawSnake;
clear;
gameMainInterface;
sleep $speed
done
}
mainInterface &
main=$!
# move snake
function moveDirectionUpdate()
{
if [[ $(( $1+$2 )) -eq 0 || $1 -eq $2 ]];then
return;
fi
case $2 in
$left)
kill -36 $main
;;
$right)
kill -37 $main
;;
$up)
kill -38 $main
;;
$down)
kill -39 $main
;;
esac
}
#監(jiān)聽(tīng)上下左右鍵的輸入
#watch input
function watchInput()
{
curDirection=$left
preDirection=$curDirection
while :;
do
read -s -n 1 op;
[[ $op = "q" ]] && kill -9 $! && return;
[[ $op = "A" ]] && preDirection=$curDirection && curDirection=$up && moveDirectionUpdate $preDirection $curDirection;
[[ $op = "B" ]] && preDirection=$curDirection && curDirection=$down && moveDirectionUpdate $preDirection $curDirection;
[[ $op = "C" ]] && preDirection=$curDirection && curDirection=$right && moveDirectionUpdate $preDirection $curDirection;
[[ $op = "D" ]] && preDirection=$curDirection && curDirection=$left && moveDirectionUpdate $preDirection $curDirection;
done
}
watchInput;
#game over
function gameOver()
{
kill -9 $main
echo "game over."
}
trap "gameOver" 35到此這篇關(guān)于shell實(shí)現(xiàn)貪吃蛇的示例代碼的文章就介紹到這了,更多相關(guān)shell 貪吃蛇內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Linux/Nginx如何查看搜索引擎蜘蛛爬蟲(chóng)的行為
本文給大家介紹Linux/Nginx如何查看搜索引擎蜘蛛爬蟲(chóng)的行為,清楚蜘蛛的爬行情況對(duì)做SEO優(yōu)化有很大的幫助。需要的朋友通過(guò)本篇文章學(xué)習(xí)下吧2015-10-10
shell編程基礎(chǔ)之認(rèn)識(shí)與學(xué)習(xí)BASH
本文介紹下,shell基礎(chǔ)編程中有關(guān)bash的相關(guān)知識(shí),有需要的朋友參考學(xué)習(xí)下2013-11-11
解決centos7 開(kāi)機(jī)/etc/rc.local 不執(zhí)行的問(wèn)題
下面小編就為大家?guī)?lái)一篇解決centos7 開(kāi)機(jī)/etc/rc.local 不執(zhí)行的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
Linux shell 獲得字符串所在行數(shù)及位置的方法
這篇文章主要介紹了Linux shell 獲得字符串所在行數(shù)及位置的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
linux下實(shí)現(xiàn)ftp自動(dòng)備份shell腳本
ftp命令把遠(yuǎn)程計(jì)算機(jī)上的文件傳輸?shù)奖镜赜?jì)算機(jī)時(shí),需要和用戶(hù)交互。怎樣使交互過(guò)程自動(dòng)化呢2013-01-01

