Shell写的贪吃蛇游戏

上一篇 / 下一篇  2008-04-11 21:45:08 / 个人分类:Shell

游戏键:
      上: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的信号,通知他上下左右和退出的消息。另一个是贪吃蛇的主执行程序


TAG: Shell

冷冷灬酱的个人空间 引用 删除 冷冷灬酱   /   2011-08-09 09:16:35
有木有注释啊,有些看不懂额。
 

评分:0

我来说两句

Open Toolbar