📄 readme.txt
字号:
一点说明:
梦想写出完美的程序是每个程序员一生的追求,也许我就是在这个追求的过程中吧。总体感觉搞笑俄罗斯方块是个做得很烂的产品,因为其实我本人并不太喜欢玩游戏,对游戏的感觉也不如那些骨灰级玩家们好,更谈不上做好它了。所以搞笑俄罗斯方块枉叫搞笑俄罗斯方块。据不完全的统计,这个程序竟然在网络里被下载了将近一万多份,向我来信索取源码的朋友也有将250人。其中对我的帮助当然很大。在此谢谢大家。
这份代码是经过重新整理了以后的,并且附加上这份说明,希望能够对大家有所帮助。也许在以后的阅读中您就会发现:这些程序真是做的烂,风格不好,方法不当,所以希望阅读者能够多扔鸡蛋:)扔死为止(hehe) email:yousp@yeah.net。同时也希望这份开放的源代码能够继续做下去,毕竟还是有那么多喜欢小游戏的朋友。
游晶
http://www.cxlife.com
2001年10月9日 凌晨 南昌大学
下边是关于源代码的说明:(感谢 Mu Gen 不断的提问题,下边是许多关于他的问题的回答)
(1) 我的俄罗斯方块的具体原理是这样的:(从源程序里贴了部分讲解,用Delphi写的)
//---------------------------------------------------------------------
type
TBlockCell=record <---- 表示每一个方快,其中包含两种信息,一种是颜色信息,
Empty: Boolean; <---- 另外一种表示的是,该位置是空还是实。如:
Color: TColor;
end;
1 1 0 0 1 1 1 1
1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 表示的是一个方快 0 0 0 0 表示的是一横
当然这里颜色值我就没有写出来了,每一个位置都是一个 TBlockCell 类型的数组单元。
//---------------------------------------------------------------------
type
TBoxArray = Array [1..MLen,1..MLen] of TBlockCell; //单个方块对应的数组
TMapData = Array [1..MapWid,1..MapHei] of TBlockCell; //当前记录
前边介绍的是方块数组,而TMapData 表示的则是背景数组:
背景数组其实和 TBoxArray 是一样的,只不过大小和功能有点不一样。
TBoxArray 是动的,而 TMapData 是静止的。TMapData中同样也是每一个格子表示是否为空,
外加颜色信息。
开始的时候背景里完全为空:
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 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
当第一个方块出现的时候,情形是这样的:
0 0 0 1 1 x x 0 0 0
0 0 0 1 1 x x 0 0 0
0 0 0 x x x x 0 0 0
0 0 0 x x x x 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
( 1 表示的是方快数组里,不为空的,x 表示为空的 )
注意这个时候我还没有改变 TMapData 即背景,我只是单纯的判断是否该方快数组位置以下的,
在背景数组里的值是否为 1 ,为 1 就表示不能下降了,下边有物体挡住了。
如果为 1 如下:
0 0 0 1 1 x x 0 0 0
0 0 0 1 1 x x 0 0 0
0 0 0 1 x x x 0 0 0
0 0 0 x x x x 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
那么这个方快就被挡在原来的位置,把它写到 TMapData 数组里就可以,然后开始一个新的循环。
写完之后如下:
0 0 0 1 1 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 1 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
当然我这里讲的很简单,里边有很多细节问题。最重要的是:
a 坐标变换 b 方快旋转(矩阵旋转变换)
c 最好把方快和背景分别写成类(我没有实现,当然我很想实现)
(2) 使用 CanGo 函数判断是否可以向 x,y 位置移动
这个函数判断是否可以将方快数组移动到背景数组的 X,Y 位置!
下边直接在程序上解释:
======= 2001-09-28 15:39:00 您在来信中写道:=======
function CanGo(X,Y: Integer;B: TBoxArray): Boolean;
var
i,j: Integer;
Flag: Boolean;
begin
if (X<1) or (X>MapWid) or //判断是否出了边界,1 到 MapWid ……
(Y<1) or (Y>MapHei) then
begin
CanGo := false; //如果指定的 X,Y不在背景数组内,不可以移动到此位置
Exit;
end;
Flag := true;
for i := X to X+MLen-1 do //从背景数组的 X,Y位置开始判断,是否方块和背景同一位置有非空块
for j := Y to Y+MLen-1 do
begin
// 如果 Map 的 [i,j] 位置不为空 并且 方块数组的[i-X+1,j-Y+1] 位置不为空 那么不能将方快移动到这个位置
if (Map[i,j].Empty <>EmptyBlock{true}) and (B[i-X+1,j-Y+1].Empty <>EmptyBlock{=true}) then
Flag := false;
end;
CanGo := Flag;
end;
= = = = 0 0 0 0 0
b b b b 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
= = = = 表示当前方块,如果要下降,
将当前的 X 不变 ,y + 1 做测试:
如当前 x=1 y=1 那么要下降的话就测试 x=1,y=2位置,如图中的 b b b b
这个时候就可以发现,= = = = 和 b b b b 都不为空,其实就是要移动到的位置已经被占用了,
所以就被挡住了!
(3) 关于如何做方块的旋转
旋转的时候,复制当前的方快数组到另外一个B数组,用该旋转后的变换数组去和背景数组比较,
如果这个时候有冲突,我就不做旋转了,否则就进行旋转。
扫描数组的过程有两个:
function GetWidth(B: TBoxArray): Integer;
function GetHeight(B: TBoxArray): Integer;
分别用来获得一个方快的高度和宽度,因为4*4数组里,往往不是满的如:
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0 的宽度和高度都为2
还有一个 ScanEmptyLine 过程扫描整个背景数组,看有没有添满1的行,这样的行可以消掉,然后
刷新屏幕,实现消行效果。
(4) 为什么获取 5,6 号方块高度和宽度时必须修正?
SetBoxArray(Box[5],1,'1000');
SetBoxArray(Box[5],2,'1100');
SetBoxArray(Box[5],3,'0100');
SetBoxArray(Box[5],4,'0000');
SetBoxArray(Box[6],1,'0100');
SetBoxArray(Box[6],2,'1100');
SetBoxArray(Box[6],3,'1000');
SetBoxArray(Box[6],4,'0000');
这两个是 5号和6号方块,你说这个样子他们的高度和宽度分别为多少?
应该分别是: 3 和 2 吧。
但是我的GetHeight算法中是这样处理:扫描每一行,看有多少个1 ,最多的1的个数为高度或者宽度,
但显然这个方法对 5号和6号方块不适用,所以必须修正。
怎样修正代码里就很明白了!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -