JavaScript must be enabled in order for you to see "WP Copy Data Protect" effect. However, it seems JavaScript is either disabled or not supported by your browser. To see full result of "WP Copy Data Protector", enable JavaScript by changing your browser options, then try again.

Game Script using Bash


隔了幾天沒發文章,所以今天來發一篇輕鬆的文章,是前陣子我在這裡看到的,是使用Bash來撰寫遊戲俄羅斯方塊踩地雷貪食蛇等遊戲的Script,最後還附上超酷的偽螢幕保護程式,所以廢話不多說,趕緊來體驗一下,如下:

1) 俄羅斯方塊(用方向鍵做操作)
#vi Tetris.sh
#!/bin/bash
# Tetris Game
# 10.21.2003 xhchen<[email]xhchen@winbond.com.tw[/email]>
#APP declaration
APP_NAME="${0##*[\\/]}"
APP_VERSION="1.0"
#顏色定義
cRed=1
cGreen=2
cYellow=3
cBlue=4
cFuchsia=5
cCyan=6
cWhite=7
colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)
#位置和大小
iLeft=3
iTop=2
((iTrayLeft = iLeft + 2))
((iTrayTop = iTop + 1))
((iTrayWidth = 10))
((iTrayHeight = 15))
#顏色設置
cBorder=$cGreen
cScore=$cFuchsia
cScoreValue=$cCyan
#控制信號
#改遊戲使用兩個進程,一個用於接收輸入,一個用於遊戲流程和顯示界面;
#當前者接收到上下左右等按鍵時,通過向後者發送signal的方式通知後者。
sigRotate=25
sigLeft=26
sigRight=27
sigDown=28
sigAllDown=29
sigExit=30
#七中不同的方塊的定義
#通過旋轉,每種方塊的顯示的樣式可能有幾種
box0=(0 0 0 1 1 0 1 1)
box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)
#所有其中方塊的定義都放到box變量中
box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
#各種方塊旋轉後可能的樣式數目
countBox=(1 2 2 2 4 4 4)
#各種方塊再box數組中的偏移
offsetBox=(0 1 3 5 7 11 15)
#每提高一個速度級需要積累的分數
iScoreEachLevel=50 #be greater than 7
#運行時數據
sig=0 #接收到的signal
iScore=0 #總分
iLevel=0 #速度級
boxNew=() #新下落的方塊的位置定義
cBoxNew=0 #新下落的方塊的顏色
iBoxNewType=0 #新下落的方塊的種類
iBoxNewRotate=0 #新下落的方塊的旋轉角度
boxCur=() #當前方塊的位置定義
cBoxCur=0 #當前方塊的顏色
iBoxCurType=0 #當前方塊的種類
iBoxCurRotate=0 #當前方塊的旋轉角度
boxCurX=-1 #當前方塊的x坐標位置
boxCurY=-1 #當前方塊的y坐標位置
iMap=() #背景方塊圖表
#初始化所有背景方塊為-1, 表示沒有方塊
for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done
#接收輸入的進程的主函數
function RunAsKeyReceiver()
{
local pidDisplayer key aKey sig cESC sTTY
pidDisplayer=$1
aKey=(0 0 0)
cESC=`echo -ne "\033"`
cSpace=`echo -ne "\040"`
#保存終端屬性。在read -s讀取終端鍵時,終端的屬性會被暫時改變。
#如果在read -s時程序被不幸殺掉,可能會導致終端混亂,
#需要在程序退出時恢復終端屬性。
sTTY=`stty -g`
#捕捉退出信號
trap "MyExit;" INT TERM
trap "MyExitNoSub;" $sigExit
#隱藏光標
echo -ne "\033[?25l"
while :
do
#讀取輸入。注-s不回顯,-n讀到一個字符立即返回
read -s -n 1 key
aKey[0]=${aKey[1]}
aKey[1]=${aKey[2]}
aKey[2]=$key
sig=0
#判斷輸入了何種鍵
if [[ $key == $cESC && ${aKey[1]} == $cESC ]]
then
#ESC鍵
MyExit
elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]
then
if [[ $key == "A" ]]; then sig=$sigRotate #<向上鍵>
elif [[ $key == "B" ]]; then sig=$sigDown #<向下鍵>
elif [[ $key == "D" ]]; then sig=$sigLeft #<向左鍵>
elif [[ $key == "C" ]]; then sig=$sigRight #<向右鍵>
fi
elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate #W, w
elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown #S, s
elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft #A, a
elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight #D, d
elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown #空格鍵
elif [[ $key == "Q" || $key == "q" ]] #Q, q
then
MyExit
fi
if [[ $sig != 0 ]]
then
#向另一進程發送消息
kill -$sig $pidDisplayer
fi
done
}
#退出前的恢復
function MyExitNoSub()
{
local y
#恢復終端屬性
stty $sTTY
((y = iTop + iTrayHeight + 4))
#顯示光標
echo -e "\033[?25h\033[${y};0H"
exit
}
function MyExit()
{
#通知顯示進程需要退出
kill -$sigExit $pidDisplayer
MyExitNoSub
}
#處理顯示和遊戲流程的主函數
function RunAsDisplayer()
{
local sigThis
InitDraw
#掛載各種信號的處理函數
trap "sig=$sigRotate;" $sigRotate
trap "sig=$sigLeft;" $sigLeft
trap "sig=$sigRight;" $sigRight
trap "sig=$sigDown;" $sigDown
trap "sig=$sigAllDown;" $sigAllDown
trap "ShowExit;" $sigExit
while :
do
#根據當前的速度級iLevel不同,設定相應的循環的次數
for ((i = 0; i < 21 - iLevel; i++))
do
sleep 0.02
sigThis=$sig
sig=0
#根據sig變量判斷是否接受到相應的信號
if ((sigThis == sigRotate)); then BoxRotate; #旋轉
elif ((sigThis == sigLeft)); then BoxLeft; #左移一列
elif ((sigThis == sigRight)); then BoxRight; #右移一列
elif ((sigThis == sigDown)); then BoxDown; #下落一行
elif ((sigThis == sigAllDown)); then BoxAllDown; #下落到底
fi
done
#kill -$sigDown $$
BoxDown #下落一行
done
}
#BoxMove(y, x), 測試是否可以把移動中的方塊移到(x, y)的位置, 返回0則可以, 1不可以
function BoxMove()
{
local j i x y xTest yTest
yTest=$1
xTest=$2
for ((j = 0; j < 8; j += 2))
do
((i = j + 1))
((y = ${boxCur[$j]} + yTest))
((x = ${boxCur[$i]} + xTest))
if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth))
then
#撞到牆壁了
return 1
fi
if ((${iMap[y * iTrayWidth + x]} != -1 ))
then
#撞到其他已經存在的方塊了
return 1
fi
done
return 0;
}
#將當前移動中的方塊放到背景方塊中去,
#並計算新的分數和速度級。(即一次方塊落到底部)
function Box2Map()
{
local j i x y xp yp line
#將當前移動中的方塊放到背景方塊中去
for ((j = 0; j < 8; j += 2))
do
((i = j + 1))
((y = ${boxCur[$j]} + boxCurY))
((x = ${boxCur[$i]} + boxCurX))
((i = y * iTrayWidth + x))
iMap[$i]=$cBoxCur
done
#消去可被消去的行
line=0
for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth))
do
for ((i = j + iTrayWidth - 1; i >= j; i--))
do
if ((${iMap[$i]} == -1)); then break; fi
done
if ((i >= j)); then continue; fi
((line++))
for ((i = j - 1; i >= 0; i--))
do
((x = i + iTrayWidth))
iMap[$x]=${iMap[$i]}
done
for ((i = 0; i < iTrayWidth; i++))
do
iMap[$i]=-1
done
done
if ((line == 0)); then return; fi
#根據消去的行數line計算分數和速度級
((x = iLeft + iTrayWidth * 2 + 7))
((y = iTop + 11))
((iScore += line * 2 - 1))
#顯示新的分數
echo -ne "\033[1m\033[3${cScoreValue}m\033[${y};${x}H${iScore} "
if ((iScore % iScoreEachLevel < line * 2 - 1))
then
if ((iLevel < 20))
then
((iLevel++))
((y = iTop + 14))
#顯示新的速度級
echo -ne "\033[3${cScoreValue}m\033[${y};${x}H${iLevel} "
fi
fi
echo -ne "\033[0m"
#重新顯示背景方塊
for ((y = 0; y < iTrayHeight; y++))
do
((yp = y + iTrayTop + 1))
((xp = iTrayLeft + 1))
((i = y * iTrayWidth))
echo -ne "\033[${yp};${xp}H"
for ((x = 0; x < iTrayWidth; x++))
do
((j = i + x))
if ((${iMap[$j]} == -1))
then
echo -ne " "
else
echo -ne "\033[1m\033[7m\033[3${iMap[$j]}m\033[4${iMap[$j]}m[]\033[0m"
fi
done
done
}
#下落一行
function BoxDown()
{
local y s
((y = boxCurY + 1)) #新的y坐標
if BoxMove $y $boxCurX #測試是否可以下落一行
then
s="`DrawCurBox 0`" #將舊的方塊抹去
((boxCurY = y))
s="$s`DrawCurBox 1`" #顯示新的下落後方塊
echo -ne $s
else
#走到這兒, 如果不能下落了
Box2Map #將當前移動中的方塊貼到背景方塊中
RandomBox #產生新的方塊
fi
}
#左移一列
function BoxLeft()
{
local x s
((x = boxCurX - 1))
if BoxMove $boxCurY $x
then
s=`DrawCurBox 0`
((boxCurX = x))
s=$s`DrawCurBox 1`
echo -ne $s
fi
}
#右移一列
function BoxRight()
{
local x s
((x = boxCurX + 1))
if BoxMove $boxCurY $x
then
s=`DrawCurBox 0`
((boxCurX = x))
s=$s`DrawCurBox 1`
echo -ne $s
fi
}
#下落到底
function BoxAllDown()
{
local k j i x y iDown s
iDown=$iTrayHeight
#計算一共需要下落多少行
for ((j = 0; j < 8; j += 2))
do
((i = j + 1))
((y = ${boxCur[$j]} + boxCurY))
((x = ${boxCur[$i]} + boxCurX))
for ((k = y + 1; k < iTrayHeight; k++))
do
((i = k * iTrayWidth + x))
if (( ${iMap[$i]} != -1)); then break; fi
done
((k -= y + 1))
if (( $iDown > $k )); then iDown=$k; fi
done
s=`DrawCurBox 0` #將舊的方塊抹去
((boxCurY += iDown))
s=$s`DrawCurBox 1` #顯示新的下落後的方塊
echo -ne $s
Box2Map #將當前移動中的方塊貼到背景方塊中
RandomBox #產生新的方塊
}
#旋轉方塊
function BoxRotate()
{
local iCount iTestRotate boxTest j i s
iCount=${countBox[$iBoxCurType]} #當前的方塊經旋轉可以產生的樣式的數目
#計算旋轉後的新的樣式
((iTestRotate = iBoxCurRotate + 1))
if ((iTestRotate >= iCount))
then
((iTestRotate = 0))
fi
#更新到新的樣式, 保存老的樣式(但不顯示)
for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
do
boxTest[$j]=${boxCur[$j]}
boxCur[$j]=${box[$i]}
done
if BoxMove $boxCurY $boxCurX #測試旋轉後是否有空間放的下
then
#抹去舊的方塊
for ((j = 0; j < 8; j++))
do
boxCur[$j]=${boxTest[$j]}
done
s=`DrawCurBox 0`
#畫上新的方塊
for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
do
boxCur[$j]=${box[$i]}
done
s=$s`DrawCurBox 1`
echo -ne $s
iBoxCurRotate=$iTestRotate
else
#不能旋轉,還是繼續使用老的樣式
for ((j = 0; j < 8; j++))
do
boxCur[$j]=${boxTest[$j]}
done
fi
}
#DrawCurBox(bDraw), 繪製當前移動中的方塊, bDraw為1, 畫上, bDraw為0, 抹去方塊。
function DrawCurBox()
{
local i j t bDraw sBox s
bDraw=$1
s=""
if (( bDraw == 0 ))
then
sBox="\040\040"
else
sBox="[]"
s=$s"\033[1m\033[7m\033[3${cBoxCur}m\033[4${cBoxCur}m"
fi

for ((j = 0; j < 8; j += 2))
do
((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY))
((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]})))
#\033[y;xH, 光標到(x, y)處
s=$s"\033[${i};${t}H${sBox}"
done
s=$s"\033[0m"
echo -n $s
}
#更新新的方塊
function RandomBox()
{
local i j t
#更新當前移動的方塊
iBoxCurType=${iBoxNewType}
iBoxCurRotate=${iBoxNewRotate}
cBoxCur=${cBoxNew}
for ((j = 0; j < ${#boxNew[@]}; j++))
do
boxCur[$j]=${boxNew[$j]}
done
#顯示當前移動的方塊
if (( ${#boxCur[@]} == 8 ))
then
#計算當前方塊該從頂端哪一行"冒"出來
for ((j = 0, t = 4; j < 8; j += 2))
do
if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
done
((boxCurY = -t))
for ((j = 1, i = -4, t = 20; j < 8; j += 2))
do
if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi
if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
done
((boxCurX = (iTrayWidth - 1 - i - t) / 2))
#顯示當前移動的方塊
echo -ne `DrawCurBox 1`
#如果方塊一出來就沒處放,Game over!
if ! BoxMove $boxCurY $boxCurX
then
kill -$sigExit ${PPID}
ShowExit
fi
fi
#清除右邊預顯示的方塊
for ((j = 0; j < 4; j++))
do
((i = iTop + 1 + j))
((t = iLeft + 2 * iTrayWidth + 7))
echo -ne "\033[${i};${t}H "
done
#隨機產生新的方塊
((iBoxNewType = RANDOM % ${#offsetBox[@]}))
((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]}))
for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++))
do
boxNew[$j]=${box[$i]};
done
((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]}))
#顯示右邊預顯示的方塊
echo -ne "\033[1m\033[7m\033[3${cBoxNew}m\033[4${cBoxNew}m"
for ((j = 0; j < 8; j += 2))
do
((i = iTop + 1 + ${boxNew[$j]}))
((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]}))
echo -ne "\033[${i};${t}H[]"
done
echo -ne "\033[0m"
}
#初始繪製
function InitDraw()
{
clear
RandomBox #隨機產生方塊,這時右邊預顯示窗口中有方快了
RandomBox #再隨機產生方塊,右邊預顯示窗口中的方塊被更新,原先的方塊將開始下落
local i t1 t2 t3
#顯示邊框
echo -ne "\033[1m"
echo -ne "\033[3${cBorder}m\033[4${cBorder}m"
((t2 = iLeft + 1))
((t3 = iLeft + iTrayWidth * 2 + 3))
for ((i = 0; i < iTrayHeight; i++))
do
((t1 = i + iTop + 2))
echo -ne "\033[${t1};${t2}H||"
echo -ne "\033[${t1};${t3}H||"
done
((t2 = iTop + iTrayHeight + 2))
for ((i = 0; i < iTrayWidth + 2; i++))
do
((t1 = i * 2 + iLeft + 1))
echo -ne "\033[${iTrayTop};${t1}H=="
echo -ne "\033[${t2};${t1}H=="
done
echo -ne "\033[0m"
#顯示"Score"和"Level"字樣
echo -ne "\033[1m"
((t1 = iLeft + iTrayWidth * 2 + 7))
((t2 = iTop + 10))
echo -ne "\033[3${cScore}m\033[${t2};${t1}HScore"
((t2 = iTop + 11))
echo -ne "\033[3${cScoreValue}m\033[${t2};${t1}H${iScore}"
((t2 = iTop + 13))
echo -ne "\033[3${cScore}m\033[${t2};${t1}HLevel"
((t2 = iTop + 14))
echo -ne "\033[3${cScoreValue}m\033[${t2};${t1}H${iLevel}"
echo -ne "\033[0m"
}
#退出時顯示GameOVer!
function ShowExit()
{
local y
((y = iTrayHeight + iTrayTop + 3))
echo -e "\033[${y};0HGameOver!\033[0m"
exit
}
#顯示用法.
function Usage
{
cat << EOF
Usage: $APP_NAME
Start tetris game.
-h, --help display this help and exit
--version output version information and exit
EOF
}
#遊戲主程序在這兒開始.
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
Usage
elif [[ "$1" == "--version" ]]; then
echo "$APP_NAME $APP_VERSION"
elif [[ "$1" == "--show" ]]; then
#當發現具有參數--show時,運行顯示函數
RunAsDisplayer
else
bash $0 --show& #以參數--show將本程序再運行一遍
RunAsKeyReceiver $! #以上一行產生的進程的進程號作為參數
fi
#chmod a+x Tetris.sh
#./Tetris.sh

2) 踩地雷(用a/m/space/方向鍵來操作)
#vi Minesweeper.sh
#!/bin/bash
MAX_H=8
MAX_H_1=$(( MAX_H -1 ))
MAX_W=8
MAX_W_1=$(( MAX_W -1 ))
TOTAL=$(( MAX_H * MAX_W ))
res=$TOTAL
MINUS_NUM=10
cur_x=0
cur_y=0
map=( m m m m m m m m
m m 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0)
map2=( u u u u u u u u
u u u u u u u u
u u u u u u u u
u u u u u u u u
u u u u u u u u
u u u u u u u u
u u u u u u u u
u u u u u u u u)
draw(){
tput cup $(($MAX_H+1)) 0
for(( i=0; i do
printf "%s %s %s %s %s %s %s %s\n" "${map[@]:$i:8}"
done
}
draw2(){
local c=$(($cur_y * MAX_W + $cur_x))
tput cup 0 0
for(( i=0; i do
printf "%s %s %s %s %s %s %s %s\n" "${map2[@]:$i:8}"
done
tput cup $cur_y $(($cur_x<<1))
echo -ne "\033[1;47m${map2[$c]}\033[m"
}
random(){
local tmp i j
for (( i=0; i do
(( j = $RANDOM % TOTAL))
tmp=${map[$i]}
map[$i]=${map[$j]}
map[$j]=$tmp
done
}
modify(){
local i j c u d l r ul ur dl dr
for (( i=0; i do
for (( j=0; j do
c=$((j * MAX_W + i))

if (( j != 0 )) ; then
u=$((c - MAX_W))
(( i != 0 )) && ul=$((u - 1 )) || ul=
(( i < MAX_W_1 )) && ur=$((u + 1 )) || ur=
else u= ul= ur=
fi
if (( j < MAX_H_1 )) ; then
d=$((c + MAX_W))
(( i != 0 )) && dl=$((d - 1 )) || ul=
(( i < MAX_W_1 )) && dr=$((d + 1 )) || ur=
else d= dl= dr=
fi
(( i != 0 )) && l=$((c - 1 )) || l=
(( i < MAX_W_1 )) && r=$((c + 1 )) || r=
if [ ${map[$c]} = m ] ; then
[ -n "$u" ] && [[ "${map[$u]}" =~ [0-8] ]] && (( map[$u]++ ))
[ -n "$d" ] && [[ "${map[$d]}" =~ [0-8] ]] && (( map[$d]++ ))
[ -n "$l" ] && [[ "${map[$l]}" =~ [0-8] ]] && (( map[$l]++ ))
[ -n "$r" ] && [[ "${map[$r]}" =~ [0-8] ]] && (( map[$r]++ ))
[ -n "$ul" ] && [[ "${map[$ul]}" =~ [0-8] ]] && (( map[$ul]++ ))
[ -n "$ur" ] && [[ "${map[$ur]}" =~ [0-8] ]] && (( map[$ur]++ ))
[ -n "$dl" ] && [[ "${map[$dl]}" =~ [0-8] ]] && (( map[$dl]++ ))
[ -n "$dr" ] && [[ "${map[$dr]}" =~ [0-8] ]] && (( map[$dr]++ ))
fi
done
done
}
modify2(){
# cur_x
# cur_y
# echo \($1, $2\)
local c=$(( $2 * MAX_W + $1 )) u d l r ul ur dl dr
if [[ "${map2[$c]}" = u ]] ; then
if (( $2 != 0 )) ; then
u=$((c - MAX_W))
(( $1 != 0 )) && ul=$((u - 1 )) || ul=
(( $1 < MAX_W_1 )) && ur=$((u + 1 )) || ur=
else u= ul= ur=
fi
if (( $2 < MAX_H_1 )) ; then
d=$((c + MAX_W))
(( $1 != 0 )) && dl=$((d - 1 )) || dl=
(( $1 < MAX_W_1 )) && dr=$((d + 1 )) || dr=
else d= dl= dr=
fi
(( $1 != 0 )) && l=$((c - 1 )) || l=
(( $1 < MAX_W_1 )) && r=$((c + 1 )) || r=
if [[ "${map[$c]}" = m ]] ; then
draw
echo you dead. && exit
elif [[ "${map[$c]}" =~ [1-8] ]] ; then
map2[$c]=${map[$c]}
(( res-- ))
elif [[ "${map[$c]}" = 0 ]] ; then
map2[$c]=' '
(( res-- ))
[ -n "$u" ] && [[ "${map2[$u]}" = u ]] && modify2 $1 $(( $2-1 ))
[ -n "$ul" ] && [[ "${map2[$ul]}" = u ]] && modify2 $(( $1-1 )) $(( $2-1 ))
[ -n "$ur" ] && [[ "${map2[$ur]}" = u ]] && modify2 $(( $1+1 )) $(( $2-1 ))
[ -n "$d" ] && [[ "${map2[$d]}" = u ]] && modify2 $1 $(( $2+1 ))
[ -n "$dl" ] && [[ "${map2[$dl]}" = u ]] && modify2 $(( $1-1 )) $(( $2+1 ))
[ -n "$dr" ] && [[ "${map2[$dr]}" = u ]] && modify2 $(( $1+1 )) $(( $2+1 ))
[ -n "$l" ] && [[ "${map2[$l]}" = u ]] && modify2 $(( $1-1 )) $2
[ -n "$r" ] && [[ "${map2[$r]}" = u ]] && modify2 $(( $1+1 )) $2
fi
fi
}
open_all(){
local c=$(( $2 * MAX_W + $1 )) tmp
if [[ "${map[$c]}" = m ]] ; then
draw
echo $1, $2
echo you dead. && exit
fi
tmp=${map[$c]}
map[$c]=0
if [[ ${map2[$c]} != u ]] ; then
((++res))
map2[$c]=u
fi
modify2 $1 $2
map[$c]=$tmp
[[ $tmp = 0 ]] && map2[$c]=' ' || map2[$c]=$tmp
}
check(){
[[ $res = $MINUS_NUM ]]
}
input(){
echo -ne "\033[?25l"
local aKey=(0 0 0 0)
local cESC=`echo -ne "\033"`
local index c
while :
do
read -s -n 1 key
aKey=( "${aKey[@]:1}" "$key")
if [[ $key${aKey[2]} == $cESC$cESC ]] ; then break
elif [ "${aKey[@]:1:2}$key" = "${cESC} [A" -a $cur_y != 0 ] ; then (( cur_y-- )) # up
elif [ "${aKey[@]:1:2}$key" = "${cESC} [B" -a $cur_y != $MAX_H_1 ] ; then (( cur_y++ )) # down
elif [ "${aKey[@]:1:2}$key" = "${cESC} [C" -a $cur_x != $MAX_W_1 ] ; then (( cur_x++ )) # right
elif [ "${aKey[@]:1:2}$key" = "${cESC} [D" -a $cur_x != 0 ] ; then (( cur_x-- )) # left
elif [ "$key" = "" ] ; then modify2 $cur_x $cur_y # space
elif [ "$key" = "a" ] ; then open_all $cur_x $cur_y
elif [ "$key" = "m" ] ; then
c=$((cur_y*MAX_W+cur_x))
if [[ ${map2[$c]} = u ]] ; then
map2[$c]=M
elif [[ ${map2[$c]} = M ]] ; then
map2[$c]='?'
elif [[ ${map2[$c]} = '?' ]] ; then
map2[$c]=u
fi
else continue
fi
draw2
#draw
check && break
done
echo -ne "\033[?25h"
}
clear
random
modify
draw2
#draw
input
draw2
draw
tput cup $(( (MAX_H<<1) + 2 )) 0
check && echo Clear time is ${SECONDS}s. || echo Quit by user.
#chmod a+x Minesweeper.sh
#./Minesweeper.sh

3) 貪食蛇(用方向鍵做操作)
#vi Snake.sh
#!/bin/bash
max_x=40
max_y=40
hx=20 hy=20
tx=20 ty=20
len=1
cur_len=0
need_food=1
level0=0.1
level1=0.05
level2=0.025
direct=u
input(){
echo -ne "\033[?25l"
local aKey=(0 0 0 0)
local cESC=`echo -ne "\033"`
local index
while :
do
read -s -n 1 key
aKey=( "${aKey[@]:1}" "$key")
if [[ $key${aKey[2]} = $cESC$cESC ]] ; then kill -29 $1; break
elif [[ "${aKey[@]:1:2}$key" = "${cESC} [A" ]] ; then kill -25 $1 ## direct=u
elif [[ "${aKey[@]:1:2}$key" = "${cESC} [B" ]] ; then kill -26 $1 ## direct=d
elif [[ "${aKey[@]:1:2}$key" = "${cESC} [C" ]] ; then kill -27 $1 ## direct=r
elif [[ "${aKey[@]:1:2}$key" = "${cESC} [D" ]] ; then kill -28 $1 ## direct=l
else continue
fi
done
echo -ne "\033[?25h"
}
draw_head(){
tput cup $2 $(( $1<<1 ))
echo -ne "\033[1;47m \033[m"
}
draw_tail(){
tput cup $2 $(( $1<<1 ))
echo -ne "\033[1;40m \033[m"
}
run(){
trap '[[ $direct != d ]] && direct=u' 25
trap '[[ $direct != u ]] && direct=d' 26
trap '[[ $direct != l ]] && direct=r' 27
trap '[[ $direct != r ]] && direct=l' 28
trap 'exit' 29
while :
do
eval "[[ \"\$m${hx}_${hy}\" = f ]] && (( ++len )) && need_food=1"
draw_head $hx $hy
eval m${hx}_${hy}=$direct
case $direct in
u) (( --hy )); (( hy < 0 )) && break ;;
d) (( ++hy )); (( hy > max_y )) && break ;;
r) (( ++hx )); (( hx > max_x )) && break ;;
l) (( --hx )); (( hx < 0 )) && break ;;
esac
eval "[ -n \"\${m${hx}_${hy}}\" -a ! \"\${m${hx}_${hy}}\" = f ] && break"
(( ++cur_len ))
if (( len < cur_len )) ; then
(( --cur_len ))
eval local d=\$m${tx}_${ty}
draw_tail $tx $ty
unset m${tx}_${ty}
case $d in
u) (( --ty ));;
d) (( ++ty ));;
r) (( ++tx ));;
l) (( --tx ));;
esac
fi
if [ $need_food = 1 ] ; then
draw_food && need_food=0
fi
sleep $level1
done
kill $1
}
draw_food(){
local fx=$(( $RANDOM % max_x + 1 ))
local fy=$(( $RANDOM % max_y + 1 ))
eval local f=\$m${fx}_${fy}
if [[ -z $f ]] ; then
tput cup $fy $(( $fx<<1 ))
eval m${fx}_${fy}=f
echo -ne "\033[1;45m \033[m"
return 0
fi
return 1
}
draw_wall(){
for (( i=0; i<=max_x; i++ ))
do
tput cup 0 $(( $i<<1 ))
eval m${i}_0=w
echo -ne "\033[1;46m \033[m"
done
for (( i=0; i<=max_x; i++ ))
do
eval m${i}_$max_y=w
tput cup $max_y $(( $i<<1 ))
echo -ne "\033[1;46m \033[m"
done
for (( j=0; j<=max_y; j++ ))
do
tput cup $j 0
echo -ne "\033[1;46m \033[m"
tput cup $j $(( max_x<<1 ))
echo -ne "\033[1;46m \033[m"
eval m0_$j=w m${max_x}_$j=w
done
}
clear
draw_wall
run $$&
input $!
#chmod a+x Snake.sh
#./Snake.sh

4) 偽螢幕保護程式(用/r/f/s/h來做操作)
#vi Screen.sh
#!/bin/sh
declare -i f=75 s=13 r=2000 t=0 c=1 n=0 l=0
declare -ir w=$(tput cols) h=$(tput lines)
declare -i x=$((w/2)) y=$((h/2))
declare -ar v=( [00]="\x83" [01]="\x8f" [03]="\x93"
[10]="\x9b" [11]="\x81" [12]="\x93"
[21]="\x97" [22]="\x83" [23]="\x9b"
[30]="\x97" [32]="\x8f" [33]="\x81" )
OPTIND=1
while getopts "f:s:r:h" arg; do
case $arg in
f) ((f=($OPTARG>19 && $OPTARG<101)?$OPTARG:$f));;
s) ((s=($OPTARG>4 && $OPTARG<16 )?$OPTARG:$s));;
r) ((r=($OPTARG>0)?$OPTARG:$r));;
h) echo -e "Usage: pipes [OPTION]..."
echo -e "Animated pipes terminal screensaver.\n"
echo -e " -f [20-100]\tframerate (D=75)."
echo -e " -s [5-15]\tprobability of a straight fitting (D=13)."
echo -e " -r LIMIT\treset after x characters (D=2000)."
echo -e " -h\t\thelp (this screen).\n"
exit 0;;
esac
done
tput smcup
tput reset
tput civis
while ! read -t0.0$((1000/$f)) -n1; do
# New position:
(($l%2)) && ((x+=($l==1)?1:-1))
((!($l%2))) && ((y+=($l==2)?1:-1))
# Loop on edges (change color on loop):
((c=($x>$w || $x<0 || $y>$h || $y<0)?($RANDOM%7-1):$c))
((x=($x>$w)?0:(($x<0)?$w:$x)))
((y=($y>$h)?0:(($y<0)?$h:$y)))
# New random direction:
((n=$RANDOM%$s-1))
((n=($n>1||$n==0)?$l:$l+$n))
((n=($n<0)?3:$n%4))
# Print:
tput cup $y $x
echo -ne "\033[1;3${c}m\xe2\x94${v[$l$n]}"
(($t>$r)) && tput reset && tput civis && t=0 || ((t++))
l=$n
done
tput rmcup
#chmod a+x Screen.sh
#./Screen.sh


◎以上就是Game Script的幾個經典範例,至於剩下的部分就留給看倌們自行品嘗了,收工!

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
This site is protected by WP-CopyRightPro