题 目 : 俄罗斯方块游戏 姓 名 : 学 号 :
院(系): 信息工程学院
2013年9月1日
1
编号:
程序设计课程设计文档
一、题目意义和设计思想
1、题目意义: 俄罗斯方块(英文:Tetris, 俄文:Тетрис)是一款风靡全球的电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。 俄罗斯方块作为一个已经有较长存在历史而又风靡全球的经典游戏,很多的人已经用很多种不同的程序语言开发并实现了它。本设计的目的,旨在开发一个用C语言在turboc编译器下编写,可以在DOS环境下运行的彩色俄罗斯方块。同时,更主要的目的是增强自己的程序设计水平。 2、设计思想: 通过turbo c2.0的绘图来实现一系列的游戏界面。游戏实现过程大致如下: 用到的数据结构 : 二维数组: int zxp[23][10],zxpcolor[23][10]; /*记录主游戏区信息,共20行,10列,前3行为玩家多提供些操作时间,zxp[x][x]记录方块的有无(0表示无,1表示有),zxpcolor[x][x]记录方块的颜色(其值的范围:0~15,分别表示16种不同的颜色)*/ 结构体:struct rlist /*记录游戏得分前十名的成绩*/ { int rgrade; /*游戏等级*/ int rlnum; /*消除的行数*/ int rpoint; /*游戏的分数*/ }rl[10]; struct blocktype { int bktp[4][4]; int color; }bt[19]; /*记录所有方块的形状(共19种)及颜色*/
2
struct p_ztemp { int x,y,bp[4][4]; int color; }tempbt; /*在预览区与游戏窗口(主显屏)之间做缓冲存储*/ struct blocktype pre; /*记录预览区方块信息*/ 游戏菜单包括: “新游戏(new game)”、“上次游戏(last game)”、“排行榜(ranking list)”和“退出游戏(quit the game)”。 主流程图: 游戏的设计思想大致就是上面这样。
3
二、采用的主要技术、遇到的难点和解决方法
1、采用的主要技术: (1)采用C语言编写,turbo c2.0编译器编译运行。 (2)用二维数组来表示方块,例如: int bt[4][4]={{0,1,1,0}, {0,1,0,0}, {0,1,0,0}, {0,0,0,0}};表示: (3)采用了图形学: 用到了graphics.h 头文件和BGI图形驱动,及数学上的坐标系。 (4)采用了随机函数和时间函数: 用到了stdlib.h和time.h头文件,用时间函数time()产生一个随即种子,在用随机函数srand()产生一个随机数(例如:srand((time(NULL)); )作为随即产生方块的依据。 (5)采用了延迟函数: 用到了dos.h头文件中的延迟函数delay(),用于方块下落的时间间隔。 2、遇到的难点和解决方法: (1)方块的下移、左移和右移问题: 刚开始没有加判断,即使有障碍物(阻挡方块下移(左移或右移)的方块)阻挡,方块依然会下移(左移或右移),从而把障碍物给覆盖掉。 解决方法:加了三个函数,分别为下移判断函数、左移判断函数和右移判断函数。在方块下移(左移或右移)之前先用判断函数判断是否有障碍物阻挡,如果有就不下移(左移或右移)。 (2)方块旋转问题: 不知道方块的形状该怎样进行旋转,刚开始试图用数学上的知识找到某种映射关系,但是没能成功。 解决方法:用了一个自己感觉很笨的方法,将19种方块形状线性地放在一个结构体数组里: struct blocktype { int bktp[4][4]; int color; }bt[19]; 将每一类方块形状按顺时针旋转(每次旋转90度)后的形状按先后顺序线性地放在上面的结构体数组里。例如:将方块 和 分别放在bt[1]和bt[2],当 方块为bt[1]时按下旋转键只需将bt[1]的下标增加一变为bt[2],就完成了从
4
到 的旋转变化。 (3)方块下落的时间间隔问题: 这个问题很让人头疼,刚开始我是用sleep()函数作为时间间隔;可是sleep()这个函数是秒级的(最短时间可以间隔一秒(即sleep(1))),显然间隔时间太长。后来我用delay()函数(毫秒级的)作为时间间隔,说是delay(1000)间隔1秒,delay(500)间隔0.5秒;但由于现在的计算机运算速度很快,即使delay(10000)也是一闪而过,根本没有你反应的机会,在百度上搜了好久也没有找到解决的办法。 解决方法:连续写10个delay();来达到延迟的效果,可是这样还有一个小问题:控制游戏时不灵敏(反应迟钝),也就是在这10个delay()运行期间是不能进行任何操作。后来我用了一个for循环,每次循环执行一次delay()和游戏控制。这样就达到了目的。代码如下: for(i=0;i<10;i++) /*多个delay()与 \控制\交替放置,以提高操作灵敏度*/ { /*同时解决delay()在该系统下延迟过短的缺陷*/ delay(20000-grade*2000); /*等级(grade)越高,速度越快*/ while(kbhit()) /*检测是否有按键*/ { if(gamehandle(&btnum1,&btnum2)) /*通过gamehandle函数控制游戏, 如果它返回1,则返回游戏菜单*/ return; } } 就是上面这段代码(突然之间想到的)解决了这个难题。
5