"Go" shell script written by Tetris game

Source: Internet
Author: User
Tags imap

Pro-Test a very fun shell script written by Tetris game, script from Internet

#!/bin/bash

# Tetris Game
# 10.21.2003 Xhchen<[email][email protected][/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)

#位置和大小
Ileft=3
itop=2
((Itrayleft = ILeft + 2))
((itraytop = iTop + 1))
((Itraywidth = 10))
((itrayheight = 15))

#颜色设置
Cborder= $cGreen
Cscore= $cFuchsia
Cscorevalue= $cCyan

#控制信号
#改游戏使用两个进程, one for receiving input, one for game flow and display interface;
#当前者接收到上下左右等按键时, inform the latter by sending signal to the latter.
Sigrotate=25
Sigleft=26
Sigright=27
Sigdown=28
sigalldown=29
Sigexit=30

#七中不同的方块的定义
#通过旋转, there may be several types of styles for each block's display
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, indicates no block
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"

#保存终端属性. When Read-s reads the terminal key, the terminal's properties are temporarily changed.
#如果在read-S program is unfortunately killed, may cause terminal confusion,
#需要在程序退出时恢复终端属性.
Stty= ' Stty-g '

#捕捉退出信号
Trap "MYEXIT;" INT term
Trap "MYEXITNOSUB;" $sigExit

#隐藏光标
Echo-ne "\033[?25l"


While:
Do
#读取输入. Note-S does not echo,-N reads to a character immediately returns
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 #< up ARROW >
elif [[$key = = "B"]]; Then sig= $sigDown #< down arrow >
elif [[$key = = "D"]]; Then sig= $sigLeft #< left arrow >
elif [[$key = = "C"]]; Then sig= $sigRight #< right >
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不同, set the number of times for the corresponding loop
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), test whether the moving block can be moved to the position (x, y), return 0, 1 can not
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;
}


#将当前移动中的方块放到背景方块中去,
#并计算新的分数和速度级. (That is, once the block falls to the bottom)
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
#走到这儿, if you can't fall.
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

#更新到新的样式, save old style (but not show)
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
#不能旋转, or continue to use the old style
for ((j = 0; J < 8; J + +))
Do
boxcur[$j]=${boxtest[$j]}
Done
Fi
}


#DrawCurBox (Bdraw), draw the currently moving block, Bdraw to 1, draw on, Bdraw to 0, erase the block.
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, cursor to (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
#计算当前方块该从顶端哪一行 "Take" it.
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 =; 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 #随机产生方块, then the right pre-display window is fast
Randombox #再随机产生方块, the block in the right pre-display window is updated, and the original block will begin to fall
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"


#显示 the words "score" and "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 [["$" = = "-H" | | "$" = = "--help"]; Then
Usage
elif [["$" = = "--version"]]; Then
echo "$APP _name $APP _version"
elif [["$" = = "--show"]]; Then
When #当发现具有参数--show, run the display function
Runasdisplayer
Else
bash $--show& #以参数--show to run the program again
Runaskeyreceiver $! #以上一行产生的进程的进程号作为参数
Fi

"Go" shell script written by Tetris game

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.