
;俄罗斯方块游戏【左键】为向左 【右l键】为向右 【上下 键】为旋转
;ELS是主程序
to tu  ;建立地图数组 长25 宽20 元素为0
make tu array [25 20]
for xx 0 24 [ for yy 0 19 [ aset tu [xx yy]  0  ]  ]
end
to mv  ;键盘响应
make s1  0  ;停止标志为0，为1时则返回 进行下一个图形的计算
make pxx 0  make key 0  ;清键盘字符变量为0 pxx 为图形左右移动的偏移量
make yc 1 while yc<23 [wait 1 \  ;24行逐一
                 make zf 0  ;字符为0 如果是ASDF则为1，向左，JKL向右ZF为2，OPQ旋转3
            if key=37 then [ make zf 1] \ ;zuo
            if key=39 then [ make zf 2 ]  \;为2向右
             if key=38 or key=40  then [ make zf 3 ]  \;为3旋转
            make key 0  \ ;字符清零
            if s1=0 then [ mvv  ]  else [stop]  \ ;如果没有有效键按下，则继续，否则停止
            make yc yc+1 ]  ;进入下一行
end
to mvv  ;图形下落程序
make s1 0  ;
 make pyy 0 ;下一行
if zf=2 then  make pxx pxx+1 make pyy -1  ;R 向右移，PXX+1 PYY不动
if zf=1 then make pxx pxx-1 make pyy -1  ;L向左移PXX-1 PYY不动
   if pxx+ox>17 then [ make pxx pxx-1 make zf 0 ] ;如果已经到最右边，则不再向右
   if pxx+ox<0 then [ make pxx pxx+1 make zf 0 ] ;如果已经到最左边，则不再向左
mv0 pxx  ;将图形在图数组中的位置清为0
mv1 pxx pyy  ;判断图形在图数组中的新位置是否为0 ，为0则表示可以移动到此
if s1=1 then mv2 stop  ;如果S为1，则表示已经碰撞到其它图形，返回，接生出下一图形
mv3 pxx pyy ;不为1，则移动到下一位置
end
to mv0 pxx  ;将图形在图数组中的位置清为0
make tb ttb  ;复制一份
if  zf=3 then [make ttb0 [] ]  ;如果为3，旋转，建空表
make ci int (count ttb)/3
for ik 1 ci [;判断方向后，从图块表中逐一取出，进行相应的移动操作
     if zf=0 then  [make xx0 (first tb)+pxx make tb bf tb ] \ ;向下
     if zf=1 then [make xx0 (first tb)+pxx+1 make tb bf tb ] \;向右
     if zf=2 then [make xx0 (first tb)+pxx-1 make tb bf tb ] \ ;向左
  if zf=3 then [make xx0 (first tb)+pxx make tb bf tb ] \ ;旋转
     make yy0 (first tb)+yc-1 make tb bf tb \
     make pp0 first tb make tb bf tb  \
     if zf=3 then [ make yx aget tu [yy0 xx0]  xz ]  \ ;如果为3，旋转90度
     aset tu [yy0 xx0] 0 \ ;将图块移动前的位置清0
]
    if zf=3 then make ttb ttb0
end 
to xz ;图块数组旋转90度，只计算一格
make x10 xx0-pxx-ox 
make y10 yy0-yc+1 
   make y1 2-y10  ;3*3矩阵右旋90度
   if y1<>x10  then  make x1 y1 make y1  x10 else make x1 x10 ;矩阵右转计算
   make x1 x1+ox 
  make ttb0 lput x1 ttb0  ;保存X值
  make ttb0 lput y1 ttb0  ;保存Y值
  make ttb0 lput yx ttb0  ;保存图形号
end 
to mv1 pxx pyy  ;判断图块移动后是否发生碰撞，如有碰撞则停止
make tb ttb 
make ci int (count ttb)/3 
for ik 1 ci [ 
     make xx0 (first tb)+pxx  make tb bf tb \ 
     make yy0 (first tb)+yc+pyy make tb bf tb \ 
     make pp0 first tb make tb bf tb \ 
  if aget tu [yy0 xx0]>1 then [make s1 1 ] \ ;取出下一格，如不为0，发生碰撞
  ] 
     if s1=1 then stop  ;发生碰撞则停止移动
end 
to mv2  ;发生碰撞后的处理
make tb ttb 
make ci int (count ttb)/3
for ik 1 ci [
     make xx0 (first tb)+pxx make tb bf tb \
     make yy0 (first tb)+yc-1 make tb bf tb \
     make pp0 first tb make tb bf tb \
     aset tu [yy0 xx0] pp0
]
end
to mv3 pxx pyy  ;没有碰撞，则让图块移动一格位置
make  tb ttb
make ci int (count ttb)/3
for ik 1 ci [ ;逐一取出X Y 及图编号
     make xx0 (first tb)+pxx make tb bf tb \
     make yy0 (first tb)+yc+pyy make tb bf tb \
   make pp0 first tb make tb bf tb \
    aset tu [yy0 xx0] pp0 \  ;改变图组中相应值
     psxy pp0 xx0*20 (12-yy0)*20   \ ;向下移动一格图形
]
  if pyy<0 then [make yc yc-1] 
end
to kuai zx  ;生成图块 ZX是图块编号
make ox  zx ;把图形编号保存到OX
setpc (random 14)%15  ;随机产生14种颜色
if ox>17 then [ pr [数字不能大于17！] stop ] 
make tux random 7 ;随机生成1-7种图形
make ka array [ 3 3]  ;建立3*3的数组
 fillarray ka item tux tuzu  ;填充这个数组，图组数组从tuzu中得到
 make tuxing item tux tuzu  ;保存这个数组为字符串
make ttb [] ;建立空表
for py 0 2 [ k1 py ]  ;逐一生成图块的每一行 共三行
end 
to k1 py ;生成成一行
pu make px  0
for kk py*3  py*3+2  [ if aget tu [py px+ox ] >1 then [ pd setpc 12 setfont 1 55 1 tt [游戏结束] toplevel ] ] ;如果生成的图块与图组中相应元素有碰撞则终止
 for kk py*3  py*3+2  [ \ 
                 if aget ka [kk] =1 then [ \ 
                   new stamprect 10 10 true  \  
                   aset ka [kk] pid  \  
                   aset  tu [py px+ox ] pid   \  
               make pxox px+ox  \  
               make ttb lput pxox ttb  \
           make ttb  lput py ttb \
           make ppd pid  make ttb lput ppd  ttb  \
                    psxy pid  pxox*20 240-py*20 ] \ 
               make px px+1 ]  
end
to els  ;主程序
cs tu
make ph  520
make pw 420
setpc 12 setw 8
 pu rt 90 fd 190 lt 90 pd  setpattern random 19 stamprect  pw ph  true  setpattern 0  stamprect  pw ph pu fd ph/2+40 ;生成具有底纹图案的游戏背景
lt 90 fd 100 rt 90 ht setfont 1 35 1 tt [俄罗斯方块]
tx ;生成7种图形块的数组
label loop 
make ox (random 17)-1 ;随机产生新生图形X座标
kuai ox ;新一个生成X为OX的图形
mv ; 移动处理
go loop  ;不断循环
end
to tx ;7 种图形
make tuzu   [ [1 0 1 1 0 1 1 1 1 ][ 1 1 0 0 1 0 0 1 1 ][ 0 1 1 0 1 0 0 1 1 ] [ 1 1 1 1 1 1 1 1 1 ] [ 0 1 0 0 1 0 1 1 1 ] [ 0 1 0 1 1 1 0 1 0 ] [1 0 0 0 1 0 0 0 1][0 1 0  0 1 0  0 1 0]]
end
