正文

[收藏]简单俄罗斯方块教程2005-11-14 16:38:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/billgacsli/6932.html

分享到:

nully  http://www.programfan.com/club/showbbs.asp?id=120594 /*先写原理:    本次的俄罗斯方块代码出其的简单,比我去年写的四十几K要小得多实际上核心代码只有3-4K,而且很容易理解,适合有一点C语言基础并对此有兴趣的人.    这前面只粗略讲解核心算法:    这里把游戏的关键设计放在三个盒子和一个坐标上:    大盒子:一个两维数组,记录着方块点阵的开与关(把游戏的舞台想像成一个点阵),在下面也把这个东西称为地图    两个5*5小盒子:两维数组,一个盛放着正在下落的方块,一个盛放在下一个下落的方块(即next),当然这两个也必须想像成一个点阵:如长条的点阵为:      00000      00100      00100      00100      00100    现在你只要有这么一个概念:一个不断定时下落的小盒子从大盒子顶部下降到底部,之后再将next盒子放在下落盒子,再进行下一轮的下落...中间的控制等尚不要太着急.    现在面临着一个问题:    下落的盒子和地图之间要怎么联系起来?一个好的方法是再定义一个坐标:x,y,保存着小盒子左上角在地图上对应的下标(位置),即当x = 0, y = 0时,小盒子处于地图的左上部.如此,当小盒子需要移动时,即只须要改变x,y的值.    现在说说旋转.    小盒子保存着当前下落形状的点阵,那么旋转就只须要将这个点阵旋转90度:例如:00000    0000000100    0000000100 -> 0111100100    0000000100    00000这一点实现起来还是不太难的.    判断碰撞    通常这种情况只须要在有移动小盒或旋转盒子时发生:也即点阵非空是互斥的,当小盒要向下移(x++)时,如果小盒里的点阵与地图上的点阵(非空的地方)重叠,则不能下移,(卡住了),旋转则转换后的形状与地图有冲突则要放弃旋转.    到了这里,你应该有一个大概的了解了,至于怎样在屏幕上画出来,这个是比较简单的,下面的代码会慢慢与你解释.*//*平台:DOS+TC2.0*/#include #include #include       /*这里须要读取系统运行时间来作为定时器*/#include   /*很不幸,TC2的简单图形,让我放弃了用*/#include      /*win32+openGL来讲解.*/#define MAX_X       14   /*可见最大X*/#define MAX_Y       21   /*可见最大Y*/                       /*我们定义了最大的可见X和Y,那么即还有不                         可见的部分,事实上地图(大盒子)里的左右                         两侧和底部各两行都被1填充,这样大大简化                         出界的判断,事实上,在本例中没有这样的                         代码,因为旁边有一圈1阻止小盒子越出大                         盒子的按制范围                        */#define MAX_C       7    /*最大种类,这个无须解释*/#define KEY_UP      'w'  /*定义上下左右按按键*/#define KEY_DOWN    's'#define KEY_LEFT    'a'#define KEY_RIGHT   'd'#define KEY_ESC     27   /*退出*/typedef int BOOL;#define FALSE 0#define TRUE 1           /*这几个TC中没有...自己定义一下吧:)*//*时钟结构*/typedef struct {           /*时钟结构*/    BOOL enabled;          /*时钟是否开启*/    unsigned int intervel; /*定时间隔*/    unsigned int lasttime; /*这个属于内部使用变量*/} Timer;/**现在进入了编程的初质阶段*在开始处我会写出所有的函数原形,以及它们的作用*main函数在程序的最后,你可以在这里看到整个游戏的组织架构*很好,它只有几十行,并且非常容易理解,当然,还是先看一下函数原形*及解释*//******************************************************\*                函数原形及说明                      *\******************************************************//*以下三个函数可以参照Timer结构体.在函数声明后面*/int GetTickCount();        /*返回电脑或操作系统运行逝去的时间*/           /*在win32环境下已包含在windows.h里边,返回的是4byte*/           /*在DOS(本代码)环境下,要自己编写,使用到BIOS.h内容*/int setTimer(Timer *t, unsigned int intv, BOOL en);           /*设置时钟t,参数分别为时钟指针,时间间隔,是否活动*/           /*时间间隔,win32下为毫秒,DOS下为1/18秒(有点低)*/BOOL testTimer(Timer *t);  /*测试时钟t是否到达定时时间*/           /*如下面这段代码:*/           /*           setTimer(&t, 1, 1); 设置1个单位的间隔           while(1) {               if(testTimer(&t)) printf("Active!\n");           }           将会定时(1个单位)在屏幕上打印Active!           一般来说testTimer必须放在循环中反复执行,激活时返回1           */void render(void);         /*唯一的绘图函数*/           /*注意,此函数重画整个地图,根据地图中的点阵,以及根据             小盒在地图的中坐标在恰当位置画出小盒子*/           /*DOS的图形当然是很低的,但,全屏绘图在这里还是过得去             的,我用的是双缓冲,交换绘图,这样感觉好点*/void initMap(void);        /*初始化地图(大盒子)*/           /*之前提到过在这个两维数组中有一圈为1的东西来阻止             小盒子出界,这就是生成这一圈的函数*/void newGame();            /*新建一个游戏*/           /*这个函数初始化一几个时钟和建造第一个下落的小盒子*/           /*当然建造完后要生成一个个的预览*/void rotateBox(int box1[5][5], int box2[5][5]);           /*核心函数成员,把box1逆时针旋转90度,并保存到box2中*/void rebuidNext();           /*核心函数成员,生成下一个方块*/int drop();           /*核心函数成员,将下落的盒子向下移(实际上增加下落盒             子的Y值而已,当然要判断是否与地图点阵重叠*/           /*与地图重叠,无法完成下落操作,返回0*/void putBox();           /*在这之上,下落的盒子与地图之前是独立的两个两维数*/           /*当下落失败后,小盒子要回到顶端再次重新执行下落,这*/           /*时原来的盒子内容当然就要变成地图上的内容了,putBox             就是将下落盒子的内容根据XY写到地图上*/void clear();           /*这个函数在下落失败并putBox后执行,扫描整个地图*/           /*清除掉满行的点阵,具体细节在函数内讲*/int move(int dir);           /*左右移动下落盒子,dir指出向左还是向右,这个与drop             是一样的*/int test(int mx, int my, int box[5][5]);           /*这个比较重点,判断box在mx,my为坐标上,与地图上的             非空点阵是否有重叠.很通用的一个函数*/int rotate();           /*旋转下落的盒子,当然如果转了之后与地图有冲突,会             取消转动,返回0,但返回的值好像没什么用~*/int newfall();           /*创建下落元素,把"下一个"预览的内容复制到下落盒子*/           /*并将下落的盒子移动到地图顶部,当然这个过程,如果顶             部有冲突,会返回0,这时说明已经满了...gameOver*/int main();           /*终于到了最后的主函数,在这里可以看到整个游戏的架*/           /*构,包括游戏主循环,键盘处理等...*/

阅读(312) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册