记得8月份写过俄罗斯方块,那会全是用坐标表示的。包括所有方块的变换,甚至方块的表示。导致程序内部许多的case语句,甚为麻烦。代码量也有近1800行左右。而且写完后bug很多,修正也修正不完,异常头痛便放弃了。

现在看看《编程之美》的俄罗斯方块的思路,又想起vczh用脚本的写的俄罗斯方块,就又起了兴趣。便重新设计完成了,这次基本没什么bug了。只不过操作习惯上和QQ的俄罗斯方块还有些不同。

1.       在底部的时候,如果按住旋转不放,则会停留原地旋转。原因是为了检测接触底部时旋转不插入墙壁,就同接触左右墙壁一样,做了调整方块坐标处理。处理方法是根据旋转后方块的坐标加上(减去)最大列(最小列)在减去(左)右边界得到。底部也是这样计算的。当然有了这样的检测便出现了这样的小小的bug,不过我相信没人会在底部按住不放的。

2.       这次方块全部存储在一个一维数组中,通过指针的变换来改变方块种类与旋转状态,但是为了方便操作,就拷贝到了一个二维数组中。起初设计是一个四维数组,这样就方便多了,但是VS2008的编译器却不能编译通过,int[4][4]int **p的转换不成功,朋友说是编译器问题。后来经Lend3d说,很多项目都是不用大于二维的数组的,于是干脆就用了一维数组,本来要听从他意见用结构表示一个低二位的数组元素,但是初始化和使用都不是很方便。

3.       另外关于GDI缓冲,试用了一下,但是作用貌似不大,不知道原因。关于这方面的知识援助还是要感谢HAM2008的帮助。



贴个头文件出来就可以知道大致做法了。
#ifndef TETRIS_H
#define TETRIS_H

#pragma once

extern int Container[18][10];//容纳方块的空间
extern int current_block[4][4];

/****************************
* 方块的主要行为
****************************
*/

class Tetris
{
public:
    Tetris();
    
~Tetris();
    
void GenerateBlock();
    
void StepLeft();
    
void StepRight();
    
void StepDown();
    
void Rotate();
    
void CaculateScore();
    
void IsOver();
public:
    
bool lost;
    
int score;//得分
    int GetX();
    
int GetY();
private:
    inline 
int CaculateMinCol();
    inline 
int CaculateMinRow();
    inline 
int CaculateMaxCol();
    inline 
int CaculateMaxRow();

    
void CaculateBlockBoundary();
    
bool DetectCollision();
    
void CopyToContainer();
    
void CopyToBlock();

    
int *block;
    
int total_rotate;
    
int kind;

    
int offset_x;
    
int offset_y;

    
int min_col,max_col;
    
int min_row,max_row;
}
;

#endif //TETRIS_H

可能自己设计上的能力还是不足吧,有些函数是不得以写的,比如四个inline函数,因为计算的时候用的是四个循环,计算完就要跳出两层循环。
难道用goto,如果直接return则后面的代码执行不到了,不得以做了四个辅助函数。

源代码下载:TetrisV1.0
可执行文件下载:TetrisV1.0.exe 如果不能运行可到微软下载VS2008的 redist_x86