游戏键:
上:w, i
下:s, k
左:a, j
右:d, l
退出:q
代码:
#!/bin/bash
ac=(0 0 0)
cESC=`echo -ne "\33"`
echo -ne "\33[?25l"
function DetectInput
{
while [[ 1 ]]
do
read -s -n 1 c
ac[0]=${ac[1]}
ac[1]=${ac[2]}
ac[2]=$c
echo -ne "\r \r"
ks=0
if [[ ${ac[1]} == $cESC && ${ac[2]} == $cESC ]]
then
ks=-1
elif [[ ${ac[0]} == $cESC && ${ac[1]} == "[" ]]
then
if [[ $c == 'A' ]]; then ks=37;
elif [[ $c == 'D' ]]; then ks=36;
elif [[ $c == 'B' ]]; then ks=39;
elif [[ $c == 'C' ]]; then ks=38;
fi
else
if [[ $c == "a" || $c == "j" || $c == "A" || $c == "J" ]]
then
ks=36
elif [[ $c == "w" || $c == "i" || $c == "W" || $c == "I" ]]
then
ks=37
elif [[ $c == "d" || $c == "l" || $c == "D" || $c == "L" ]]
then
ks=38
elif [[ $c == "s" || $c == "k" || $c == "S" || $c == "K" ]]
then
ks=39
elif [[ $c == "q" || $c == "Q" ]]
then
ks=-1
fi
fi
if [[ $ks == -1 ]]
then
echo Quit.
AllExit
elif [[ $ks != 0 ]]
then
kill -$ks $pidShowSnake
fi
done
}
sSaveStty=`stty -g`
function MyExit
{
echo -ne "\33[?25h"
stty $sSaveStty
exit
}
function AllExit
{
kill -40 $pidShowSnake
MyExit
}
if [[ $1 != "--showsnake" ]]
then
eval $0" --showsnake "$$"&"
trap "MyExit" TERM
trap "AllExit" INT
pidShowSnake=$!
DetectInput
exit
else
pidCtlSnake=$2
fi
echo sub
iSpeed=500 #time interval in millisecond
iDirection=0 #1-left, 2-up, 3-right, 4-down
iWidth=15
iHeight=15
iX=(6 7 8)
iY=(7 7 7)
iMap=()
iS=0 #Start pointer in iX
(( iTotalBox = iWidth * iHeight ))
for (( i = 0; i < iTotalBox; i++ ))
do
iMap[$i]=0
done
function RandomHeader
{
(( iNew = RANDOM % ( iTotalBox - ${#iX[@]} ) ))
for (( iNewP = 0, i = 0; iNewP < iTotalBox && i < iNew; iNewP++))
do
if (( ${iMap[$iNewP]} != 1 )); then (( i++ )); fi
done
while (( ${iMap[$iNewP]} == 1 )); do (( iNewP++ )); done
(( iNewX = iNewP % iWidth ))
(( iNewY = (iNewP - iNewX) / iWidth ))
echo -ne "\33[1m\33[35m\33[45m"
(( pX = 2 * iNewX + iLeft + 1 ))
(( pY = iNewY + iTop + 1 ))
echo -ne "\33["$pY";"$pX"H[]"
echo -ne "\33["$iCursor";1H"
echo -ne "\33[0m"
}
function InitDraw
{
clear
(( iTop = 1 ))
(( iBottom = iTop + iHeight + 1 ))
(( iLeft = 1 ))
(( iRight = iLeft + iWidth + iWidth + 1 ))
(( iCursor = iBottom + 1 ))
echo -ne "\33[1m\33[32m\33[42m"
for (( i = iLeft + 1; i < iWidth + iWidth + iLeft + 1; i++ ))
do
echo -ne "\33["$iTop";"$i"H="
echo -ne "\33["$iBottom";"$i"H="
done
for (( i = iTop; i < iHeight + iTop + 2; i++ ))
do
echo -ne "\33["$i";"$iLeft"H|"
echo -ne "\33["$i";"$iRight"H|"
done
echo -ne "\33["$iCursor";1H"
echo -ne "\33[0m"
echo -ne "\33[1m\33[33m\33[43m"
for (( i = 0; i < ${#iX[@]}; i++ ))
do
(( pX = 2 * ${iX[$i]} + iLeft + 1 ))
(( pY = ${iY[$i]} + iTop + 1 ))
(( pM = ${iY[$i]} * iWidth + ${iX[$i]} ))
iMap[$pM]=1
echo -ne "\33["$pY";"$pX"H[]"
done
echo -ne "\33["$iCursor";1H"
echo -ne "\33[0m"
RandomHeader
}
function ShiftSnake
{
(( iLastP = iS - 1 ))
if (( iLastP < 0 )); then ((iLastP = ${#iX[@]} - 1 )); fi
if (( iDir == 1 )) #left
then
(( iHX = ${iX[$iLastP]} - 1 ))
(( iHY = ${iY[$iLastP]} ))
elif (( iDir == 2 )) #up
then
(( iHX = ${iX[$iLastP]} ))
(( iHY = ${iY[$iLastP]} - 1 ))
elif (( iDir == 3 )) #right
then
(( iHX = ${iX[$iLastP]} + 1 ))
(( iHY = ${iY[$iLastP]} ))
elif (( iDir == 4 )) #down
then
(( iHX = ${iX[$iLastP]} ))
(( iHY = ${iY[$iLastP]} + 1 ))
fi
bOver=0
if (( iHX < 0 || iHY < 0 || iHX >= iWidth || iHY >= iHeight )); then bOver=1;fi
if (( bOver == 0 )); then
if (( ${iMap[iHY * iWidth + iHX]} == 1 )); then bOver=1; fi
fi
if (( bOver == 1 ))
then
kill $pidCtlSnake
(( iBottom = iBottom + 1 ))
echo -e "\33["$iBottom";0HGame over! (Score: "${#iX[@]}"00)\33[0m"
exit 0;
fi
#check if catch the new box
if (( iHX == iNewX && iHY == iNewY ))
then
for (( i = ${#iX[@]}; i > iS; i-- ))
do
(( j = $i - 1 ))
iX[$i]=${iX[$j]}
iY[$i]=${iY[$j]}
done
iX[$iS]=$iHX
iY[$iS]=$iHY
(( iNextP = iS + 1 ))
if (( iNextP >= ${#iX[@]} )); then iNextP=0; fi
echo -ne "\a"
RandomHeader
else
(( iNextP = iS + 1 ))
if (( iNextP >= ${#iX[@]} )); then iNextP=0; fi
#clear snake tailer
(( pX = 2 * ${iX[$iS]} + iLeft + 1 ))
(( pY = ${iY[$iS]} + iTop + 1 ))
(( pM = ${iY[$iS]} * iWidth + ${iX[$iS]} ))
iMap[$pM]=0
echo -ne "\33["$pY";"$pX"H "
iX[$iS]=$iHX
iY[$iS]=$iHY
fi
#draw snake header
echo -ne "\33[1m\33[33m\33[43m"
(( pX = 2 * iHX + iLeft + 1 ))
(( pY = iHY + iTop + 1 ))
(( pM = iHY * iWidth + iHX ))
iMap[$pM]=1
echo -ne "\33["$pY";"$pX"H[]"
echo -ne "\33["$iCursor";1H"
echo -ne "\33[0m"
(( iS = iNextP ))
}
trap "if (( iDir != 3 && iDir != 0 )); then iDirection=1; fi" 36
trap "if (( iDir != 4 )); then iDirection=2; fi" 37
trap "if (( iDir != 1 )); then iDirection=3; fi" 38
trap "if (( iDir != 2 )); then iDirection=4; fi" 39
trap "exit;" 40
InitDraw
(( iUSec = iSpeed * 1000 ))
while [[ 1 ]]
do
usleep $iUSec
#sleep 1
iDir=$iDirection
if (( iDir != 0 ))
then
ShiftSnake
fi
done
答疑:
在函数function AllExit()和function RandomHeader()之间的那段代码是什么意思?
是这么想的:
根据命令行参数的不同,把这个shell作为两个程序运行。
一个用于读取键盘输入,并向另一个发送36-40的信号,通知他上下左右和退出的消息。另一个是贪吃蛇的主执行程序