shell指令碼實現俄羅斯方塊

來源:互聯網
上載者:User

標籤:linux   shell   

draw  是畫出圖形介面   keytest是擷取鍵盤  tetris是整個遊戲

tetris.sh

#!/bin/bashAPP_NAME="${0##*[\\/]}"APP_VERSION="1.0"#顏色定義iSumColor=7#顏色總數cRed=1#紅色cGreen=2#綠色cYellow=3#黃色cBlue=4#藍色cFuchsia=5#紫紅色cCyan=6#青色(藍綠色)cWhite=7#白色#位置與大小marginLeft=3#邊框左邊距marginTop=2#邊框上邊距((mapLeft=marginLeft+2))#棋盤左邊距((mapTop=$marginTop+1))#棋盤上邊距mapWidth=10#棋盤寬度mapHeight=15#棋盤高度#顏色設定cBorder=$cGreencScore=$cFuchsiacScoreValue=$cCyan#控制訊號#遊戲使用兩個進程,一個用於接收輸入,一個用於遊戲流程和顯示介面;#當前者接收到上下左右等按鍵時,通過向後者發送signal的方式通知後者。sigRotate=25#向上鍵sigLeft=26sigRight=27sigDown=28sigAllDown=29#空格鍵sigExit=30#方塊定義,7大類19種樣式#前8位為方塊座標,後2位為方塊剛出現的時候的位置box0_0=(0 0 0 1 1 0 1 1 0 4)box1_0=(0 1 1 1 2 1 3 1 0 3)box1_1=(1 0 1 1 1 2 1 3 -1 3)box2_0=(0 0 1 0 1 1 2 1 0 4)box2_1=(0 1 0 2 1 0 1 1 0 3)box3_0=(0 1 1 0 1 1 2 0 0 4)box3_1=(0 0 0 1 1 1 1 2 0 4)box4_0=(0 2 1 0 1 1 1 2 0 3)box4_1=(0 1 1 1 2 1 2 2 0 3)box4_2=(1 0 1 1 1 2 2 0 -1 3)box4_3=(0 0 0 1 1 1 2 1 0 4)box5_0=(0 0 1 0 1 1 1 2 0 3)box5_1=(0 1 0 2 1 1 2 1 0 3)box5_2=(1 0 1 1 1 2 2 2 -1 3)box5_3=(0 1 1 1 2 0 2 1 0 4)box6_0=(0 1 1 0 1 1 1 2 0 3)box6_1=(0 1 1 1 1 2 2 1 0 3)box6_2=(1 0 1 1 1 2 2 1 -1 3)box6_3=(0 1 1 0 1 1 2 1 0 4)iSumType=7#方塊類型總數boxStyle=(1 2 2 2 4 4 4)#各種方塊旋轉後可能的樣式數目iScoreEachLevel=50#提升一個層級需要的分數#運行時資料sig=0#接收到的signaliScore=0#總分iLevel=0#速度級boxNext=()#下一個方塊iboxNextColor=0#下一個方塊的顏色iboxNextType=0#下一個方塊的種類iboxNextStyle=0#下一個方塊的樣式boxCur=()#當前方塊的位置定義iBoxCurColor=0#當前方塊的顏色iBoxCurType=0#當前方塊的種類iBoxCurStyle=0#當前方塊的樣式boxCurX=-1#當前方塊的x座標位置boxCurY=-1#當前方塊的y座標位置map=()#棋盤圖表#初始化所有背景方塊為-1, 表示沒有方塊for ((i = 0; i < mapHeight * mapWidth; i++))domap[$i]=-1done#接收輸入的進程的主函數function RunAsKeyReceiver(){local pidDisplayer key aKey sig cESC sTTYpidDisplayer=$1aKey=(0 0 0)cESC=`echo -ne "\033"`cSpace=`echo -ne "\040"`#儲存終端屬性。在read -s讀取終端鍵時,終端的屬性會被暫時改變。#如果在read -s時程式被不幸殺掉,可能會導致終端混亂,#需要在程式退出時恢複終端屬性。sTTY=`stty -g`#捕捉退出訊號trap "MyExit;" INT QUITtrap "MyExitNoSub;" $sigExit#隱藏游標echo -ne "\033[?25l"while :do#讀取輸入。注-s不回顯,-n讀到一個字元立即返回read -s -n 1 keyaKey[0]=${aKey[1]}aKey[1]=${aKey[2]}aKey[2]=$keysig=0#判斷輸入了何種鍵if [[ $key == $cESC && ${aKey[1]} == $cESC ]]then#ESC鍵MyExitelif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]thenif [[ $key == "A" ]]; then sig=$sigRotate#<向上鍵>elif [[ $key == "B" ]]; then sig=$sigDown#<向下鍵>elif [[ $key == "D" ]]; then sig=$sigLeft#<向左鍵>elif [[ $key == "C" ]]; then sig=$sigRight#<向右鍵>fielif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate#W, welif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown#S, selif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft#A, aelif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight#D, delif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown#空格鍵elif [[ $key == "Q" || $key == "q" ]]#Q, qthenMyExitfiif [[ $sig != 0 ]]then#向另一進程發送訊息kill -$sig $pidDisplayerfidone}#退出前的恢複MyExitNoSub(){local y#恢複終端屬性stty $sTTY((y = marginTop + mapHeight + 4))#顯示光線標echo -e "\033[?25h\033[${y};0H"exit}MyExit(){#通知顯示進程需要退出kill -$sigExit $pidDisplayerMyExitNoSub}#處理顯示和遊戲流程的主函數RunAsDisplayer(){local sigThisInitDraw#掛載各種訊號的處理函數trap "sig=$sigRotate;" $sigRotatetrap "sig=$sigLeft;" $sigLefttrap "sig=$sigRight;" $sigRighttrap "sig=$sigDown;" $sigDowntrap "sig=$sigAllDown;" $sigAllDowntrap "ShowExit;" $sigExitwhile :do#根據當前的速度級iLevel不同,設定相應的迴圈的次數for ((i = 0; i < 21 - iLevel; i++))dosleep 0.02sigThis=$sigsig=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;#下落到底fidone#kill -$sigDown $$BoxDown#下落一行done}#繪製當前方塊,傳第一個參數,0表示擦除當前方塊,1表示繪製當前方塊DrawCurBox(){local i x y bErase sBoxbErase=$1if (( bErase == 0 ))thensBox="\040\040"#用兩個空格擦除elsesBox="[]"echo -ne "\033[1m\033[3${iBoxCurColor}m\033[4${iBoxCurColor}m"fifor ((i = 0; i < 8; i += 2))do((y = mapTop + 1 + ${boxCur[$i]} + boxCurY))((x = mapLeft + 1 + 2 * (boxCurX + ${boxCur[$i + 1]})))echo -ne "\033[${y};${x}H${sBox}"doneecho -ne "\033[0m"}#移動方塊#BoxMove(y, x), 測試是否可以把移動中的方塊移到(y, x)的位置, 返回0則可以, 1不可以BoxMove(){local i x y xPos yPosyPos=$1xPos=$2for ((i = 0; i < 8; i += 2))do#方塊相對於棋盤座標((y = yPos + ${boxCur[$i]}))((x = xPos + ${boxCur[$i + 1]}))if (( y < 0 || y >= mapHeight || x < 0 || x >= mapWidth))then#撞到牆壁了return 1fiif (( ${map[y * mapWidth + x]} != -1 ))then#撞到其他已經存在的方塊了return 1fidonereturn 0;}#將方塊貼到棋盤上Box2Map(){local i j x y line#將當前移動中的方塊貼到棋盤對應的地區for ((i = 0; i < 8; i += 2))do#計算方塊相對於棋盤的座標((y = ${boxCur[$i]} + boxCurY))((x = ${boxCur[$i + 1]} + boxCurX))map[y*mapWidth+x]=$iBoxCurColor#將方塊顏色賦給地圖doneline=0for ((i = 0; i < mapHeight; i++))dofor ((j = 0; j < mapWidth; j++))do#如果棋盤上有空隙,跳出迴圈[[ ${map[i*mapWidth+j]} -eq -1 ]] && breakdone[ $j -lt $mapWidth ] && continue#說明當前行可消去,可消去行數加一(( line++ ))#第i行可被消除,將0行至第i-1行全部下移一行,從第i-1行開始移動for ((j = i*mapWidth-1; j >= 0; j--))do((x = j + mapWidth))map[$x]=${map[$j]}done#因為下移一行,第0行置空for ((i = 0; i < mapWidth; i++))domap[$i]=-1donedone[ $line -eq 0 ] && return#根據消去的行數line計算分數和速度級((x = marginLeft + mapWidth * 2 + 7))((y = marginTop + 11))((iScore += line * 2 - 1))#顯示新的分數echo -ne "\033[1m\033[3${cScoreValue}m\033[${y};${x}H${iScore}         "if ((iScore % iScoreEachLevel < line * 2 - 1))thenif ((iLevel < 20))then((iLevel++))((y = marginTop + 14))#顯示新的速度級echo -ne "\033[3${cScoreValue}m\033[${y};${x}H${iLevel}        "fifiecho -ne "\033[0m"#重新顯示背景方塊for ((i = 0; i < mapHeight; i++))do#棋盤相對於螢幕的座標((y = i + mapTop + 1))((x = mapLeft + 1))echo -ne "\033[${y};${x}H"for ((j = 0; j < mapWidth; j++))do((tmp = i * mapWidth + j))if ((${map[$tmp]} == -1))thenecho -ne "  "elseecho -ne "\033[1m\033[3${map[$tmp]}m\033[4${map[$tmp]}m[]\033[0m"fidonedone}#左移一格BoxLeft(){local x((x = boxCurX - 1))if BoxMove $boxCurY $xthenDrawCurBox 0((boxCurX = x))DrawCurBox 1fi}#右移一格BoxRight(){local x((x = boxCurX + 1))if BoxMove $boxCurY $xthenDrawCurBox 0((boxCurX = x))DrawCurBox 1fi}#向下移一格BoxDown(){local y((y = boxCurY + 1))#新的y座標if BoxMove $y $boxCurX#測試是否可以下落一行thenDrawCurBox 0#將舊的方塊抹去((boxCurY = y))DrawCurBox 1#顯示新的下落後方塊else#走到這兒, 如果不能下落了Box2Map#將當前移動中的方塊貼到背景方塊中CreateBox#產生新的方塊fi}#下落到底BoxAllDown(){local y iDown#計算能夠下落的行數iDown=0(( y = boxCurY + 1 ))while BoxMove $y $boxCurXdo(( y++ ))(( iDown++ ))doneDrawCurBox 0#將舊的方塊抹去((boxCurY += iDown))DrawCurBox 1#顯示新的下落後的方塊Box2Map#將當前移動中的方塊貼到背景方塊中CreateBox#產生新的方塊}#翻轉BoxRotate(){[ ${boxStyle[$iBoxCurType]} -eq 1 ] && return((rotateStyle = (iBoxCurStyle + 1) % ${boxStyle[$iBoxCurType]}))#將當前方塊儲存到boxTmpboxTmp=( `eval 'echo ${boxCur[@]}'` )boxCur=( `eval 'echo ${box'$iBoxCurType'_'$rotateStyle'[@]}'` )if BoxMove $boxCurY $boxCurX#測試旋轉後是否有空間放的下then#抹去舊的方塊boxCur=( `eval 'echo ${boxTmp[@]}'` )DrawCurBox 0boxCur=( `eval 'echo ${box'$iBoxCurType'_'$rotateStyle'[@]}'` )DrawCurBox 1iBoxCurStyle=$rotateStyleelse#不能旋轉,還是繼續使用老的樣式boxCur=( `eval 'echo ${boxTmp[@]}'` )fi}#準備下一個方塊PrepareNextBox(){local i x y#清除右邊預顯示的方塊if (( ${#boxNext[@]} != 0 )); thenfor ((i = 0; i < 8; i += 2))do((y = marginTop + 1 + ${boxNext[$i]}))((x = marginLeft + 2 * mapWidth + 7 + 2 * ${boxNext[$i + 1]}))echo -ne "\033[${y};${x}H\040\040"donefi#隨機產生預顯式方塊(( iBoxNextType = RANDOM % iSumType ))(( iBoxNextStyle = RANDOM % ${boxStyle[$iBoxNextType]} ))(( iBoxNextColor = RANDOM % $iSumColor + 1 ))boxNext=( `eval 'echo ${box'$iBoxNextType'_'$iBoxNextStyle'[@]}'` )#顯示右邊預顯示的方塊echo -ne "\033[1m\033[3${iBoxNextColor}m\033[4${iBoxNextColor}m"for ((i = 0; i < 8; i += 2))do((y = marginTop + 1 + ${boxNext[$i]}))((x = marginLeft + 2 * mapWidth + 7 + 2 * ${boxNext[$i + 1]}))echo -ne "\033[${y};${x}H[]"doneecho -ne "\033[0m"}#顯示新方塊CreateBox(){if (( ${#boxCur[@]} == 0 )); then#當前方塊不存在(( iBoxCurType = RANDOM % iSumType ))(( iBoxCurStyle = RANDOM % ${boxStyle[$iBoxCurType]} ))(( iBoxCurColor = RANDOM % $iSumColor + 1 ))else#當前方塊已存在, 將下一個方塊賦給當前方塊iBoxCurType=$iBoxNextType;iBoxCurStyle=$iBoxNextStyle;iBoxCurColor=$iBoxNextColorfi#當前方塊數組boxCur=( `eval 'echo ${box'$iBoxCurType'_'$iBoxCurStyle'[@]}'` )#初始化方塊起始座標boxCurY=boxCur[8];boxCurX=boxCur[9];DrawCurBox 1#繪製當前方塊if ! BoxMove $boxCurY $boxCurXthenkill -$sigExit $PPIDShowExitfiPrepareNextBox}#繪製邊框DrawBorder(){clearlocal i y x1 x2#顯示邊框echo -ne "\033[1m\033[3${cBorder}m\033[4${cBorder}m"((x1 = marginLeft + 1))#左邊框x座標((x2 = x1 + 2 + mapWidth * 2))#右邊框x座標for ((i = 0; i < mapHeight; i++))do((y = i + marginTop + 2))echo -ne "\033[${y};${x1}H||"#繪製左邊框echo -ne "\033[${y};${x2}H||"#繪製右邊框done((x1 = marginTop + mapHeight + 2))for ((i = 0; i < mapWidth + 2; i++))do((y = i * 2 + marginLeft + 1))echo -ne "\033[${mapTop};${y}H=="#繪製上邊框echo -ne "\033[${x1};${y}H=="#繪製下邊框doneecho -ne "\033[0m"#顯示"Score"和"Level"字樣echo -ne "\033[1m"((y = marginLeft + mapWidth * 2 + 7))((x1 = marginTop + 10))echo -ne "\033[3${cScore}m\033[${x1};${y}HScore"((x1 = marginTop + 11))echo -ne "\033[3${cScoreValue}m\033[${x1};${y}H${iScore}"((x1 = marginTop + 13))echo -ne "\033[3${cScore}m\033[${x1};${y}HLevel"((x1 = marginTop + 14))echo -ne "\033[3${cScoreValue}m\033[${x1};${y}H${iLevel}"echo -ne "\033[0m"}InitDraw(){clear#清屏DrawBorder#繪製邊框CreateBox#建立方塊}#退出時顯示GameOVer!ShowExit(){local y((y = mapHeight + mapTop + 3))echo -e "\033[${y};1HGameOver!\033[0m"exit}#遊戲主程式在這兒開始.if [[ "$1" == "--version" ]]; thenecho "$APP_NAME $APP_VERSION"elif [[ "$1" == "--show" ]]; then#當發現具有參數--show時,運行顯示函數RunAsDisplayerelsebash $0 --show&#以參數--show將本程式再運行一遍RunAsKeyReceiver $!#以上一行產生的進程的進程號作為參數fi


keytest.sh


#!/bin/bashGetKey(){aKey=(0 0 0) #定義一個數組來儲存3個按鍵cESC=`echo -ne "\033"`cSpace=`echo -ne "\040"`while :doread -s -n 1 key  #讀取一個字元,將讀取到的字元儲存在key中#echo $key#echo XXX aKey[0]=${aKey[1]} #第一個按鍵aKey[1]=${aKey[2]} #第二個按鍵aKey[2]=$key        #第三個按鍵if [[ $key == $cESC && ${aKey[1]} == $cESC ]]thenMyExitelif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]thenif [[ $key == "A" ]]; then echo KEYUPelif [[ $key == "B" ]]; then echo KEYDOWNelif [[ $key == "D" ]]; then echo KEYLEFTelif [[ $key == "C" ]]; then echo KEYRIGHTfifidone}GetKey


draw.sh



#!/bin/bash#位置與大小marginLeft=8#邊框左邊距marginTop=6#邊框上邊距((mapLeft=marginLeft+2))#棋盤左邊距((mapTop=$marginTop+1))#棋盤上邊距mapWidth=10#棋盤寬度mapHeight=15#棋盤高度#方塊定義,7大類19種樣式#前8位為方塊座標,後2位為方塊剛出現的時候的位置box0_0=(0 0 0 1 1 0 1 1 0 4)box1_0=(0 1 1 1 2 1 3 1 0 3)box1_1=(1 0 1 1 1 2 1 3 -1 3)box2_0=(0 0 1 0 1 1 2 1 0 4)box2_1=(0 1 0 2 1 0 1 1 0 3)box3_0=(0 1 1 0 1 1 2 0 0 4)box3_1=(0 0 0 1 1 1 1 2 0 4)box4_0=(0 2 1 0 1 1 1 2 0 3)box4_1=(0 1 1 1 2 1 2 2 0 3)box4_2=(1 0 1 1 1 2 2 0 -1 3)box4_3=(0 0 0 1 1 1 2 1 0 4)box5_0=(0 0 1 0 1 1 1 2 0 3)box5_1=(0 1 0 2 1 1 2 1 0 3)box5_2=(1 0 1 1 1 2 2 2 -1 3)box5_3=(0 1 1 1 2 0 2 1 0 4)box6_0=(0 1 1 0 1 1 1 2 0 3)box6_1=(0 1 1 1 1 2 2 1 0 3)box6_2=(1 0 1 1 1 2 2 1 -1 3)box6_3=(0 1 1 0 1 1 2 1 0 4)#繪製邊框DrawBorder(){clearlocal i y x1 x2#顯示邊框echo -ne "\033[1m\033[32m\033[42m"((x1 = marginLeft + 1))#左邊框x座標((x2 = x1 + 2 + mapWidth * 2))#右邊框x座標for ((i = 0; i < mapHeight; i++))do((y = i + marginTop + 2))echo -ne "\033[${y};${x1}H||"#繪製左邊框echo -ne "\033[${y};${x2}H||"#繪製右邊框done((x1 = marginTop + mapHeight + 2))for ((i = 0; i < mapWidth + 2; i++))do((y = i * 2 + marginLeft + 1))echo -ne "\033[${mapTop};${y}H=="#繪製上邊框echo -ne "\033[${x1};${y}H=="#繪製下邊框doneecho -ne "\033[0m"}DrawBox(){local i x y xPos yPosyPos=${box0_0[8]}xPos=${box0_0[9]}echo -ne "\033[1m\033[35m\033[45m"for ((i = 0; i < 8; i += 2))do(( y = mapTop + 1 + ${box0_0[$i]} + yPos ))(( x = mapLeft + 1 + 2 * (${box0_0[$i + 1]} + xPos) ))echo -ne "\033[${y};${x}H[]"doneecho -ne "\033[0m"}InitDraw(){clear#清屏DrawBorder#繪製邊框DrawBoxwhile :dosleep 1done}InitDraw





shell指令碼實現俄羅斯方塊

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.