#!/bin/bash 
# Tetris Game 
# 10.21.2003 xhchen
#颜色定义 
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=($ $ $ $ $ $ $) 
#各种方块旋转后可能的样式数目 
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 
#接收输入的进程的主函数 
function runaskeyreceiver() 
{ 
  local piddisplayer key akey sig cesc stty 
  piddisplayer= 
  akey=(0 0 0) 
  cesc=`echo -ne ""` 
  cspace=`echo -ne ""` 
  #保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。 
  #如果在read -s时程序被不幸杀掉,可能会导致终端混乱, 
  #需要在程序退出时恢复终端属性。 
  stty=`stty -g` 
  
  #捕捉退出信号 
  trap "myexit;" int term 
  trap "myexitnosub;" $sigexit 
  
  #隐藏光标 
  echo -ne "[?25l" 
  
  while (( 1 )) 
  do 
    #读取输入。注-s不回显,-n读到一个字符立即返回 
    read -s -n 1 key 
    
    akey[0]=$ 
    akey[1]=$ 
    akey[2]=$key 
    sig=0 
    #判断输入了何种键 
    if [[ $key == $cesc && $ == $cesc ]] 
    then 
      #esc键 
      myexit 
    elif [[ $ == $cesc && $ == "[" ]] 
    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 "[?25h[$;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 (( 1 )) 
  do 
    #根据当前的速度级ilevel不同,设定相应的循环的次数 
    for ((i = 0; 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= 
  xtest= 
  for ((j = 0; j   do 
    ((i = j + 1)) 
    ((y = $ + ytest)) 
    ((x = $ + xtest)) 
    if (( y = itrayheight || x = itraywidth)) 
    then 
      #撞到墙壁了 
      return 1 
    fi 
    if ((${imap[y * itraywidth + x]} != -1 )) 
    then 
      #撞到其他已经存在的方块了 
      return 1 
    fi 
  done 
  return 0; 
} 
#将当前移动中的方块放到背						
                        
                        PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
                
                                
                                
                                
                                
                                
                                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号