Shell腳本編寫規範推薦

#!/bin/bash  
#-------------CopyRight-------------  
#   Name:Mine Sweeping  
#   Version Number:1.00  
#   Type:game  
#   Language:bash shell  
#   Date:2005-10-26  
#   Author:BitBull  
#   Email:BitBull.cn(at)gmail.com  
#------------Environment------------  
#   Terminal: column 80 line 24  
#   Linux 2.6.9 i686  
#   GNU Bash 3.00.15  
#-----------------------------------  
 
#---------------Define--------------  
ECHO="echo -ne"
ESC="\033["
 
OK=0
FALSE=1
#--------------Variable--------------  
#ANSI ESC action  
FLASH=5
REV=7
 
#color  
NULL=0
BLACK=30
RED=31
GREEN=32
ORANGE=33
BLUE=34
PURPLE=35
SBLUE=36
GREY=37
 
#back color  
BBLACK=40
BRED=41
BGREEN=42
BORANGE=43
BBLUE=44
BPURPLE=45
BSBLUE=46
BGREY=47
 
MINE='@'
FLAG='F'
NUL=' '
SHADOW='X'
 
X=0
Y=0
CurX=1 #cur's X  
CurY=1 #cur's Y  
OCurX=1 #old cur's X  
OCurY=1 #old cur's Y  
MCount=0 #count mine  
FCount=0 #count flag  
SCount=0 #count shadow  
MXYp=0 #MXY Array's ptr  
#---------------Array----------------  
 
#if ${XY[]} == M { mine }  
#if ${XY[]} == F { flag }  
#if ${XY[]} == N { null }  
#if ${XY[]} == S { shadow }  
#if ${XY[]} == [1-8] { tip_num }  
#${XY[]} init in XYInit(i)  
 
MXY[0]=""  
 
#--------------Function--------------  
 
function SttyInit ()  
{  
        stty_save=$(stty -g) #backup stty  
 
        clear  
        trap "GameExit;" 2 15
        stty -echo  
 
        $ECHO "${ESC}?25l" #hidden cursor  
          
        return $OK  
}  
 
function GameExit ()  
{  
        stty $stty_save  
        stty echo  
        clear  
        trap 2 15
        $ECHO "${ESC}?25h${ESC}0;0H${ESC}0m"
 
        exit $OK  
}  
 
#print help  
function Help ()  
{  
        msg="Move:w s a d Dig:j Flag:f NewGame:n Exit:x   --CopyRight-- -2005-10-28 BitBull--"
        $ECHO "${ESC}${REV};${RED}m${ESC}24;1H${msg}${ESC}${NULL}m"
 
        return $OK  
}  
 
#print dialog window in screen  
function PMsg ()  
{  
        local title="$1" content="$2" greeting="$3"
 
        $ECHO "${ESC}${RED}m"
        $ECHO "${ESC}11;20H ------------------------------------------- "
        $ECHO "${ESC}12;20H|         ======>$title<======           |"
        $ECHO "${ESC}13;20H|         $content          |"
        $ECHO "${ESC}14;20H|         ======>$greeting<======           |"
        $ECHO "${ESC}15;20H ------------------------------------------- "
        $ECHO "${ESC}${NULL}m"
 
        return $OK  
}  
 
#print menu and player choose level,then ${X,Y,MCount,FCount,SCount} init  
function Menu ()  
{  
        local key  
 
        $ECHO "${ESC}6;1H${ESC}${RED}m"
cat<<MENUEND  
                       +++++++++++++++++++++++++++++  
                       +        (1) Easy           +  
                       +        (2) Normal         +  
                       +        (3) Hardly         +  
                       +        (4) Exit           +  
                       +++++++++++++++++++++++++++++  
MENUEND  
        $ECHO "${ESC}${NULL}m"
 
        while read -s -n 1 key  
        do  
                case $key in
                1) X=10;Y=10;MCount=10;FCount=10;SCount=100;break
                ;;  
                2) X=20;Y=14;MCount=28;FCount=28;SCount=280;break
                ;;  
                3) X=36;Y=18;MCount=65;FCount=65;SCount=648;break
                ;;  
                4) GameExit  
                ;;  
                esac  
        done  
 
        return $OK  
}          
 
#receive CurX CurY,put it into XY[CurX+X*(CurY-1))]  
#if $# == 3;write into XY[]  
#if $# == 2;read from XY[]  
function XYFormat ()  
{  
        local XTmp=$1 YTmp=$2
 
        if [[ $# -eq 3 ]]  
        then XY[$XTmp+$X*($YTmp-1)]=$3
        else echo ${XY[$XTmp+$X*($YTmp-1)]}  
        fi          
          
        return $OK  
}  
 
function DrawInit ()  
{  
        local DIline DIline2  
 
        DIline=$( for (( i=1; i<$((X*2)); i++ )) do $ECHO '-';done )  
        DIline2=$( for (( i=0; i<X; i++ )) do $ECHO "|${ESC}${SBLUE}mX${ESC}${NULL}m";done )  
 
        clear  
        Help  
          
        $ECHO "${ESC}1;1H+${DIline}+"
        for (( i=0; i<Y; i++ ))  
        do  
                $ECHO "${ESC}$((i+2));1H${DIline2}|"
        done  
        $ECHO "${ESC}$((Y+2));1H+${DIline}+"
 
        return $OK  
}  
 
#${XY[*]}=S  
function XYInit ()  
{  
        for (( i=1; i<=$X; i++ ))  
        do  
                for (( j=1; j<=$Y; j++ ))  
                do  
                        XYFormat $i $j S  
                done  
        done  
        return $OK  
}  
 
#check X Y  
function CheckXY ()  
{  
        local XYTmp="$1 $2"
 
        for(( i=0; i<MXYp; i++ ))  
        do  
                if [[ "${MXY[i]}" == "$XYTmp" ]]  
                then return $FALSE  
                fi  
        done  
 
        return $OK  
}  
 
#RANDOM mine's X Y  
function XYRand ()  
{  
        local XTmp YTmp  
 
        for(( i=0; i<MCount; i++ ))  
        do  
                while :   
                do  
                        XTmp=$(( RANDOM % ( X - 1 ) + 1 ))  
                        YTmp=$(( RANDOM % ( Y - 1 ) + 1 ))  
                        CheckXY $XTmp $YTmp  
 
                        if [[ "$?" == "$OK" ]]  
                        then  
                                XYFormat $XTmp $YTmp M  
                                MXY[i]="$XTmp $YTmp"
                                (( ++MXYp ))  
                                break
                        else continue
                        fi  
                done  
        done  
          
        return $OK  
}  
 
#DEBUG  
# print ${XY[*]} into ./mine.tmp  
#you can read mine.tmp to know where is mine,xixi~~:)  
#M is mine  
function DEBUGPXY ()  
{  
        rm mine.tmp>/dev/null 2>&1
        for(( i=1; i<=$Y; i++ ))  
        do  
                for(( j=1; j<=$X; j++))  
                do  
                        $ECHO "$(XYFormat $j $i)">>mine.tmp  
                done  
                $ECHO "\n">>mine.tmp  
        done  
 
        return $OK  
}  
 
#move cur  
#usage:CurMov [UP|DOWN|LEFT|RIGHT]  
function CurMov ()  
{  
        local direction=$1 Xmin=1 Ymin=1 Xmax=$X Ymax=$Y  
 
        OCurX=$CurX  
        OCurY=$CurY  
 
        case $direction        in
        "UP")        if [[ $CurY -gt $Ymin ]];then (( CurY-- ));fi  
        ;;  
        "DOWN")        if [[ $CurY -lt $Ymax ]];then (( CurY++ ));fi  
        ;;  
        "LEFT") if [[ $CurX -gt $Xmin ]];then (( CurX-- ));fi  
        ;;  
        "RIGHT")if [[ $CurX -lt $Xmax ]];then (( CurX++ ));fi  
        ;;  
        esac  
 
        if [[ $CurX != $OCurX || $CurY != $OCurY ]]  
        then DrawPoint $CurX $CurY CUR  
        fi  
 
        return $OK  
}  
 
#display point  
#include cur,flag,mine,shadow,nul,tip [1-8]  
function DrawPoint ()  
{  
        local TCurX=$(( $1 * 2 )) TCurY=$(( $2 + 1 )) Type=$3
        local TOCurX=$(( OCurX * 2 )) TOCurY=$(( OCurY + 1 ))  
        local colr=0 osign=0 sign=0
          
        case $Type in
        "CUR")  
                case $(XYFormat $OCurX $OCurY) in
                F)        colr=$PURPLE;osign=$FLAG;;  
                N)        colr=$NULL;osign=$NUL;;  
                [1-8])        colr=$ORANGE;osign=$(XYFormat $OCurX $OCurY);;  
                [SM])        colr=$SBLUE;osign=$SHADOW;;  
                esac  
 
                case $(XYFormat $CurX $CurY) in
                F)      sign=$FLAG;;  
                N)      sign=$NUL;;  
                [1-8])        sign=$(XYFormat $CurX $CurY);;  
                [SM])     sign=$SHADOW;;  
                esac  
 
                $ECHO "${ESC}${colr}m${ESC}${TOCurY};${TOCurX}H${osign}${ESC}${NULL}m"
                $ECHO "${ESC}${REV};${FLASH};${ORANGE}m${ESC}${TCurY};${TCurX}H${sign}${ESC}${NULL}m"
        ;;  
        "SHADOW")  
                $ECHO "${ESC}${SBLUE}m${ESC}${TCurY};${TCurX}H${SHADOW}${ESC}${NULL}m"
        ;;  
        "MINE")   
                $ECHO "${ESC}${REV};${RED}m${ESC}${TCurY};${TCurX}H${MINE}${ESC}${NULL}m"
        ;;  
        "FLAG")  
                $ECHO "${ESC}${TCurY};${TCurX}H${ESC}${PURPLE}m${FLAG}${ESC}${NULL}m"
        ;;  
        [1-8])  
                $ECHO "${ESC}${TCurY};${TCurX}H${ESC}${ORANGE}m${Type}${ESC}${NULL}m"
        ;;  
        "NUL")  
                $ECHO "${ESC}${TCurY};${TCurX}H${NUL}"
        esac          
 
        return $OK  
}  
 
#check xy  
function Loop ()  
{  
        local XYTmp="$1 $2"
 
        for (( i=0; i<MXYp; i++ ))  
        do  
                if [[ "$XYTmp" == "${MXY[i]}" ]]  
                then $ECHO 1
                fi  
        done  
 
        return $OK  
}  
 
#count around mine  
#A B C  
#D X E  
#F G H  
#return mine's number  
function CountM ()  
{  
        local Xmin=1 Ymin=1 Xmax=$X Ymax=$Y minecount=0 n=0
#A  
        if [[ ( $CurX -gt $Xmin ) && ( $CurY -gt $Ymin ) ]]  
        then  
                n=$( Loop $((CurX-1)) $((CurY-1)) )  
                (( minecount += n ))  
                n=0
        fi  
#B  
        if [[ $CurY -gt $Ymin ]]  
        then  
                n=$( Loop $CurX $((CurY-1)) )  
                (( minecount += n ))  
                n=0
        fi  
#C  
        if [[ ( $CurX -lt $Xmax ) && ( $CurY -gt $Ymin ) ]]  
        then  
                n=$( Loop $((CurX+1)) $((CurY-1)) )  
                (( minecount += n ))  
                n=0
        fi  
#D  
        if [[ $CurX -gt $Xmin ]]  
        then  
                n=$( Loop $((CurX-1)) $CurY )  
                (( minecount += n ))  
                n=0
        fi  
#E  
        if [[ $CurX -lt $Xmax ]]  
        then  
                n=$( Loop $((CurX+1)) $CurY )  
                (( minecount += n ))  
                n=0
        fi  
#F  
        if [[ ( $CurX -gt $Xmin ) && ( $CurY -lt $Ymax ) ]]  
        then  
                n=$( Loop $((CurX-1)) $((CurY+1)) )  
                (( minecount += n ))  
                n=0
        fi  
#G  
        if [[ $CurY -lt $Ymax ]]  
        then   
                n=$( Loop $CurX $((CurY+1)) )  
                (( minecount += n ))  
                n=0
        fi  
#H  
        if [[ ( $CurX -lt $Xmax ) && ( $CurY -lt $Ymax ) ]]  
        then  
                n=$( Loop $((CurX+1)) $((CurY+1)) )  
                (( minecount += n ))  
                n=0
        fi  
 
        return $minecount  
}  
 
#dig  
#if mine ,gameover  
#else tip around mine's number  
function Dig ()  
{  
        local key minenum=0
 
        case $(XYFormat $CurX $CurY) in
        M)  
                DrawPoint $CurX $CurY MINE  
                read -s -n 1 key  
                GameOver "Game Over"
        ;;  
        S)  
                CountM  
                minenum=$?  
                if [[ $minenum -eq $NULL ]]  
                then  
                        XYFormat $CurX $CurY N  
                        DrawPoint $CurX $CurY NUL  
                else
                        XYFormat $CurX $CurY $minenum  
                        DrawPoint $CurX $CurY $minenum  
                fi  
          
                (( SCount-- ))  
                if [[ $SCount -eq $MCount ]]  
                then GameOver "Well Done"
                fi          
        ;;  
        esac  
        DrawPoint $CurX $CurY CUR  
 
        return $OK  
}  
 
#draw flag's number  
function DrawFCount ()  
{  
        $ECHO "${ESC}22;34H${ESC};${PURPLE}mFLAG=${FCount}  ${ESC}${NULL}m"
}  
 
#sign mine  
function Flag ()  
{  
        local XYTmp="$CurX $CurY";stat=$FALSE  
 
        case $(XYFormat $CurX $CurY) in
        F)  
                for (( i=1; i<MXYp; i++ ))  
                do  
                        if [[ "${MXY[i]}" == "$XYTmp" ]]  
                        then XYFormat $CurX $CurY M;stat=$OK;break
                        fi  
                done  
                if [[ $stat == $FALSE ]]  
                then XYFormat $CurX $CurY S  
                fi  
 
                DrawPoint $CurX $CurY SHADOW  
                (( FCount++ ))  
                DrawFCount  
        ;;  
        [SM])          
                if [[ $FCount -eq $NULL ]]  
                then return $FALSE  
                fi  
 
                DrawPoint $CurX $CurY FLAG  
                XYFormat $CurX $CurY F  
                (( FCount-- ))  
                DrawFCount  
        ;;  
        esac  
        DrawPoint $CurX $CurY CUR  
 
        return $OK  
}  
 
function GameOver ()  
{  
        local key msgtitle=$1
 
        PMsg "$msgtitle" "Do you want replay?<y/n>" "Thank You"
        while read -s -n 1 key  
        do  
                case $key in
                [yY])        exec $(dirname $0)/$(basename $0);;  
                [nN])        GameExit;;  
                *)        continue;;  
                esac  
        done  
 
        return $OK          
}  
          
#main  
#drawscreen and control  
function Main ()  
{  
        local key  
 
        XYInit  
        XYRand  
############################  
# if you enable DEBUGPXY,  
#you can know where is mine  
#        DEBUGPXY  #delete this line's #  
#then cat ./mine.tmp  
############################          
 
        DrawPoint $CurX $CurY CUR  
        DrawFCount          
 
        while read -s -n 1 key  
        do  
                case $key in
                [wW])        CurMov UP;;  
                [sS])        CurMov DOWN;;  
                [aA])        CurMov LEFT;;  
                [dD])        CurMov RIGHT;;  
                [jJ])        Dig;;  
                [fF])        Flag;;  
                [nN])        exec $(dirname $0)/$(basename $0);;  
                [xX])        GameExit;;  
                esac  
        done  
 
        return $OK  
}  
#---------------Main-----------------  
 
SttyInit  
Menu #X Y MCount FCount SCount OK!  
DrawInit  
Main
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章