俄罗斯方块游戏设计文档 姓名:祁竹欣 班级:10381 目录1. 前言(游戏体验)....................................................................2. 功能描述....................................................................................3. 总体设计.................................................................................... 3.1功能模块设计..................................................................... 3.1.1 游戏执行主流程.......................................................... 3.1.2 游戏方块预览............................................................... 3.1.3 游戏方块控制............................................................... 3.1.4 游戏显示更新............................................................... 3.1.5 游戏速度分数更新...................................................... 3.1.6 游戏帮助....................................................................... 3.2函数功能描述....................................................................... 3.3 游戏规则.............................................................................. 3.4 操作方法..............................................................................4. 程序实现.................................................................................. 4.1 源码分析...................................................................... 4.1.1 初始化界面...................................................... 4.2 运行结果...................................................................... 4.2.1 游戏初始状态..................................................... 4.2.2 游戏进行状态..................................................... 5. 开发环境................................................................................. 5.1 硬件环境...................................................................5.2 软件环境....................................................................6. 结论............................................................................................7. 代码附录...................................................................................1. 前言 俄罗斯方块是一款风靡全球的掌上游戏机和PC机游戏,它造成的轰动与创造的经济价值可以说是游戏史上的一件大事。
它由俄罗斯人阿列克谢~帕基特诺夫在1984年6月利用空闲时间所编写的游戏程序,故得此名俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分它看似简单却变化无穷,俄罗斯方块上手极其简单,但是要熟练地掌握其中的操作与摆放技巧,难度却不低作为家喻户晓老少皆宜的大众游戏,其普及程度可以说是史上任何一款游戏都无法相比的相信大多数人都还记得为它痴迷得茶不思饭不想的那个俄罗斯方块的时代由于俄罗斯方块具有的教学性、动态性与知名度,也经常拿来作为游戏程序设计的练习题材 用C语言来编写俄罗斯方块这个游戏有较大优势:C语言具有各种各样的数据类型,并引入了指针概念,使得程序效率更高;C语言还包含很广泛的运算符;另外C语言具有强大的图形功能,支持多种显示器和驱动器,而且计算功能、逻辑判断能力也比较强大2. 功能描述如图2.1所示,本游戏主要实现以下几种功能: 俄罗斯方块游戏游戏显示更新功能游戏方块预览功能游戏方块控制功能游戏帮助功能游戏速度更新功能 图2.1 俄罗斯方块游戏功能描述图(1) 游戏方块预览功能在游戏过程中,当在游戏底板中出现一个游戏方块时,必须在游戏方块预览区域中出现下一个游戏方块,这样有利于游戏玩家控制游戏的策略。
由于在此游戏中存在19种不同的游戏方块,所以在游戏方块预览区域中需要显示随即生成的游戏方块2) 游戏方块控制功能通过各种条件的判断,实现对游戏方块的左移、右移、快速下移、自由下落、旋转功能,以及行满消除行的功能3) 游戏显示更新功能当游戏方块左右移动、下落、旋转时,要清除先前的游戏方块,用新坐标重绘游戏方块当消除满行时,要重绘游戏底板的当前状态4) 游戏速度分数更新功能在游戏玩家进行游戏过程中,需要按照一定的游戏规则给玩家计算游戏分数5) 游戏帮助功能玩家进入游戏后,将有对本游戏如何操作的友情提示3. 总体设计 3.1功能模块设计3.1.1 游戏执行主流程本俄罗斯方块游戏执行主流程图3.1所示在判断键值时,有左移VK_LEFT、右移VK_RIGHT、下移VK_DOWN、变形转换VK_UP、退出VK_ESC键值的判断3.1.2游戏方块预览新游戏方块将在如图3.2所示的4*4的正方形中预览使用随机数rand()来产生1~19之间的游戏方块的编号,并作为预览的方块编号其中的正方形小方块的大小为BSIZE*BSIZEBSIZE为设定的像素大小图3.2 游戏方块预览图3.1.3游戏方块控制 这是此游戏开发的重点和难点部分。
下面分别较少左移、右移、下移、旋转及满行判断的实现左移的实现过程如下:(1) 判断在当前的游戏底板中能否左移这一判断必须满足如下两个条件:游戏方块整体左移一位后,游戏方块不能超越游戏底板的左边线,否则越界;并且在游戏方块有值(值为1)的位置,游戏底板必须是没有被占用的(占用时,值为1)若满足这两个条件,则执行下面的左移动作否则不执行左移动作2)清除左移前的游戏方块3)在左移一位的位置,重新显示此游戏方块右移的实现过程如下:(1) 判断在当前游戏底板中能否右移这一判断必须满足如下两个条件:游戏方块整体右移一位后,游戏方块不能超越底板的右边线,否则越界;并且在游戏方块有值(值为1)的位置,游戏底板必须是没有被占用的(占用时,值为1)若满足这两个条件,则执行下面的右移动作否则不只执行右移动作2) 清除右移前的游戏方块3) 在右移一位的位置,重新显示此游戏方块下移的实现过程如下:(1) 判断在当前游戏底板中能否下移这一判断必须满足如下两个条件:游戏方块整体下移一位后,游戏方块不能超越游戏底板的底边线,否则越界;并且在游戏方块有值(值为1)的位置,游戏底板必须是没有被占用的(占用时,值为1)若满足这两个条件,则执行下面的下移动作。
否则,将flag_newbox标志置1,主循环中会判断此标志,若为1,则会生成下一个游戏方块,并更新预览游戏方块2) 清除下移前的游戏方块3) 在下移一位的位置,重新显示此游戏方块旋转的实现过程如下:(1) 判断在当前游戏底板中能否旋转这一判断必须满足如下条件:游戏方块整体旋转后,游戏方块不能超越游戏底板的左边线、右边线和底边线,否则越界;并且在游戏方块有值(值为1)的位置,游戏底板必须是没有被占用的(占用时,值为1)若满足这些条件,则执行下面的旋转动作否则不只执行旋转动作2) 清除旋转前的游戏方块3) 在游戏方块显示区域(4*4)不变的位置,利用保存当前游戏方块的数据结构中的next值作为旋转后形成的新游戏方块的编号,并重新显示这个编号的游戏方块当生成新的游戏方块前,执行行满的检查,判断行满的过程为:一次从下到上扫描游戏底板中的各行,若某行中1的个数等于游戏底板水平方向上的小方块的个数,则表示此行是满的找到满行后,立即将游戏底板中的数据往下顺移一行,直到游戏底板逐行扫描完毕3.1.4 游戏显示更新当游戏方块左右移动、下落、旋转时,要清除先前的游戏方块用新坐标重新绘游戏方块当消除满行时,要重绘游戏底板的当前状态。
清除方块的过程为:用先画轮廓再填充的方式,使用背景色填充小方块,然后使用前景色画一个游戏底板中的小方块循环此过程,变化当前坐标,填充及画出共16个这样的小方块这样在游戏底板中,清除了此游戏方块3.1.5 游戏速度分数更新当判断出一行满时,score变量一固定值(如10),可以把等级level看做是速度speed,因为速度speed是根据计分score值不断上升的,所以我们定义level=speed==score/speed_step,其中speed_step是每升一级所需要的分数方块下落速度加快,这是不断修改了定时计数器变量TimerCounter判断条件的结果速度越快,时间中断的间隔就越短3.1.6 游戏帮助实现比较简单,使用outtextxy()函数实现 3.2 函数功能描述(1) newtimer()函数原型:void interrupt newtimer(void)Newtimer()函数用于为新的时钟中断处理函数2) SetTimer()函数原型:void SetTimer(void interrupt(*IntProc)(void))SetTimer()函数用于设置新的时钟中断处理过程。
3) KillTimer()函数原型:void KillTimer()KillTimer()函数用于恢复原有的时钟中断处理过程4) Initialize()函数原型:void initialize(int x,int y,int m,int n)Initialize()函数用于初始化界面,具体为在传人参数x,y指明位置上面m行n列小方块,并显示积分、等级、帮助及预览游戏方块等5) DelFullRow()函数原型:int DelFullRow(int y)DelFullRow()函数用于处理删除一满行的情况Y指明具体哪一行为满行6) setFullRow()函数原型:void setFullRow(int t_boardy)setFullRow()函数用于找到满行,并调用DelFullRow()函数来处理满行t_boardy 为在游戏底板中的垂直方向的坐标值7) MkNextBox()函数原型:int MkNextBox(int box_numb)MkNextBox()函数用于生成下一个游戏方块,并返回方块号Box_numb表示当前的游戏方块号8) EraseBox()函数原型:void EraseBox(int x,int y,int box_numb)EraseBox()函数用于清除(x,y)位置开始的编号为box_numb的游戏方块。
9) show_box()函数原型:void show box(int x,int y,int box_numb,int color)show_box()函数用于显示(x,y)位置开始的编号为box_numb 的、颜色值为color 的游戏方块10) MoveAble()函数原型:int MoveAble(int x,int y,int box_numb,int direction)MoveAble()函数判断是否可以移动x,y)为当前方块位置,box_numb为方块号,direction为方向标志,返回true和false11) 主函数main()整个游戏的主控部分3.3游戏规则俄罗斯方块的基本规则: 1、一个用于摆放小型正方形的平面虚拟场地,其标准大小:行宽为10,列高为20,以每个小正方形为单位 2、一组由4个小型正方形组成的规则图形,英文称为Tetromino,中文通称为方块共有7种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名I:一次最多消除四层 J(左右):最多消除三层,或消除二层 L:最多消除三层,或消除二层 O:消除一至二层 S(左右):最多二层,容易造成孔洞 Z (左右):最多二层,容易造成孔洞 T:最多二层 (1) 部分游戏有单格方块,可以穿透固定的方块到达最下层空位。
其他的改版中出现更多特别的造型方块会从区域上方开始缓慢继续落下 (2) 玩家可以做的操作有:以90度为单位旋转方块,以格子为单位左右移动方块,让方块加速落下 (3) 方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下 (4) 当区域中某一列横向格子全部由方块填满,则该列会消失并成为玩家的得分同时删除的列数越多,得分指数上升 (5) 当固定的方块堆到区域最上方而无法消除层数时,则游戏结束6) 一般来说,游戏还会提示下一个要落下的方块,熟练的玩家会计算到下一个方块,评估现在要如何进行由于游戏能不断进行下去对商业用游戏不太理想,所以一般还会随着游戏的进行而加速提高难度 3、 通过设计者预先设置的随机发生器不断地输出单个方块到场地顶部,以一定的规则进行移动、旋转、下落和摆放,锁定并填充到场地中每次摆放如果将场地的一行或多行完全填满,则组成这些行的所有小正方形将被消除,并且以此来换取一定的积分或者其他形式的奖励而未被消除的方块会一直累积,并对后来的方块摆放造成各种影响 4、如果未被消除的方块堆放的高度超过场地所规定的最大高度(并不一定是20或者玩家所能见到的高度),则游戏结束。
具体到每一款不同的游戏,其中的细节规则都可能有千差万别,但是以上的基本规则是相同的3.4 操作方法1. 按游戏界面的"开始"按钮或者F2键来开始游戏,自己使用右边的窗口,对手使用左边的窗口 2. 键盘操作:系统缺省设置使用右边的窗口,用光标操作,"←"左移一格;"→"右移一格;"↑"旋转方块;↓ 方块丢下(方块下落到底),"End"健可以一格格的下落,用户还可以自定义习惯的按键来操作游戏 3. 计分牌显示的内容:“分数”为双方本局的分数,计分标准为下落一个块10分,一次消一行100分、2行200分、3行400分、4行800分 “等级”为双方的游戏设置等级,当分数达到一定的值,等级就会提升、速度加快 “行数”第一行为双方消的行数,第二行是送给对方的行数 “比分”为双方赢的局数4. 程序实现 4.1源码分析4.1.1 初始化界面 玩家进行游戏时,需要对游戏界面进行初始化工作此代码被main()函数调用主要进行的工作如下:(1) 循环调用line()函数绘制当前游戏板2) 调用ShowScore()函数显示初始的成绩,初始成绩为03) 调用ShowSpeed()函数显示初始的速度(等级),初始速度1。
/************初始化界面********参数说明:* x,y为左上角坐标* m,n对应于Vertical_boxs,Horizontal_boxs* 分别表示纵横方向上方块的个数(以方块为单位)* BSIZE Sys_x Sys_y****************************************/void initialize(int x,int y,int m,int n){int i,j,oldx;oldx=x;for(j=0;j
此时,分数初始化为0,等级默认为1.游戏当前设置为成绩每增加30分等级就升一级,升级后游戏方块在原来基础上下落速度有所加快,这主要是变化了定时器的时间间隔的缘故用户可使用键盘左移键、右移键、上移键和下移键,分别进行左移、右移、旋转和下落操作用户可按ESC键退出游戏4.2.2 游戏进行状态图4.3 为游戏等级提升了一级后的状态,级别越高,游戏方块下落速度越快5.开发环境5.1硬件环境:服务器 CPU:PIII 500以上,内存:256M客户机 CPU:P200MMX以上,内存:32M以上5.2软件环境:Visual S 2.0 以上6.结论俄罗斯方块的制作的完成,让我学到了很多经过一个月的编程与调试,我学到了很多知识,这为我接下来的学习做好铺垫在编写代码的过程中我遇到了很多小麻烦,有些小问题弄得我焦头烂额我必须仔细认真的把代码检查很多遍,从而使我对这些代码印象深刻,增加了我的知识在这过程中我也遇到很多问题:比如代码忘记了或者有些代码不认识,我都会去翻书,或者去查资料,增加了我对代码的熟悉度7. 代码附录/*加载头文件*/ #include #include #include #include /*图形库函数*/#include #define __CPPARGS#define MINBOXSIZE 15 /* 最小方块的尺寸 */ #define BGCOLOR 7 /* 背景着色 */ #define GX 200 #define GY 10 #define SJNUM 10000 /* 每当玩家打到一万分等级加一级*/ /* 按键码*/ #define VK_LEFT 0x4b00 #define VK_RIGHT 0x4d00 #define VK_DOWN 0x5000 #define VK_UP 0x4800 #define VK_HOME 0x4700 #define VK_END 0x4f00 #define VK_SPACE 0x3920 #define VK_ESC 0x011b #define VK_ENTER 0x1c0d /* 定义俄罗斯方块的方向(我定义他为4种)*/ #define F_DONG 0 #define F_NAN 1 #define F_XI 2 #define F_BEI 3 #define NEXTCOL 20 /* 要出的下一个方块的纵坐标*/ #define NEXTROW 12 /* 要出的下一个方块的横从标*/ #define MAXROW 14 /* 游戏屏幕大小*/ #define MAXCOL 20 #define SCCOL 100 /*游戏屏幕大显示器上的相对位置*/ #define SCROW 60 int gril[22][16]; /* 游戏屏幕坐标*/ int col=1,row=7; /* 当前方块的横纵坐标*/ int boxfx=0,boxgs=0; /* 当前寺块的形壮和方向*/ int nextboxfx=0,nextboxgs=0,maxcol=22;/*下一个方块的形壮和方向*/ int minboxcolor=6,nextminboxcolor=6; int num=0; /*游戏分*/ int dj=0,gamedj[10]={18,16,14,12,10,8,6,4,2,1};/* 游戏等级*/ /* 以下我用了一个3维数组来纪录方块的最初形状和方向*/ int boxstr[7][4][16]={{ {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}}, { {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}}, { {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}}, { {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0}, {1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}}, { {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0}}, { {1,1,0,0,1,1,0,0,0,0,0,0.0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0.0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0.0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0.0,0,0,0}}, { {0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {0,1,0,0,1,1,1,0,0,0,0,0.0,0,0,0}, {0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0}} }; /* 随机得到当前方块和下一个方块的形状和方向*/ void boxrad(){ minboxcolor=nextminboxcolor; boxgs=nextboxgs; boxfx=nextboxfx; nextminboxcolor=random(14)+1; if(nextminboxcolor==4||nextminboxcolor==7||nextminboxcolor==8) nextminboxcolor=9; nextboxfx=F_DONG; nextboxgs=random(7); } /*初始化图形模试*/ void init(int gdrive,int gmode){ int errorcode; initgraph(&gdrive,&gmode,"D:\\tc\\"); errorcode=graphresult(); if(errorcode!=grOk){ printf("error of: %s",grapherrormsg(errorcode)); exit(1); } } /* 在图形模式下的清屏 */ void cls() { setfillstyle(SOLID_FILL,0); setcolor(0); bar(0,0,640,480); } /*在图形模式下的高级清屏*/ void clscr(int a,int b,int c,int d,int color){ setfillstyle(SOLID_FILL,color); setcolor(color); bar(a,b,c,d); } /*最小方块的绘制*/ void minbox(int asc,int bsc,int color,int bdcolor){ int a=0,b=0; a=SCCOL+asc; b=SCROW+bsc; clscr(a+1,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE,color); if(color!=BGCOLOR){ setcolor(bdcolor); line(a+1,b+1,a-1+MINBOXSIZE,b+1); line(a+1,b+1,a+1,b-1+MINBOXSIZE); line(a-1+MINBOXSIZE,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE); line(a+1,b-1+MINBOXSIZE,a-1+MINBOXSIZE,b-1+MINBOXSIZE); } } /*游戏中出现的文字*/ void txt(int a,int b,char *txt,int font,int color){ setcolor(color); settextstyle(0,0,font); outtextxy(a,b,txt); } /*windows 绘制*/ void win(int a,int b,int c,int d,int bgcolor,int bordercolor){ clscr(a,b,c,d,bgcolor); setcolor(bordercolor); line(a,b,c,b); line(a,b,a,d); line(a,d,c,d); line(c,b,c,d); } /* 当前方块的绘制*/ void funbox(int a,int b,int color,int bdcolor){ int i,j; int boxz[4][4]; for(i=0;i<16;i++) boxz[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(boxz[i][j]==1) minbox((j+row+a)*MINBOXSIZE,(i+col+b)*MINBOXSIZE,color,bdcolor); } /*下一个方块的绘制*/ void nextfunbox(int a,int b,int color,int bdcolor){ int i,j; int boxz[4][4]; for(i=0;i<16;i++) boxz[i/4][i%4]=boxstr[nextboxgs][nextboxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(boxz[i][j]==1) minbox((j+a)*MINBOXSIZE,(i+b)*MINBOXSIZE,color,bdcolor); } /*时间中断定义*/ #define TIMER 0x1c int TimerCounter=0; void interrupt ( *oldhandler)(__CPPARGS); void interrupt newhandler(__CPPARGS){ TimerCounter++; oldhandler(); } void SetTimer(void interrupt (*IntProc)(__CPPARGS)){ oldhandler=getvect(TIMER); disable(); setvect(TIMER,IntProc); enable(); } /*由于游戏的规则,消掉都有最小方块的一行*/ void delcol(int a){ int i,j; for(i=a;i>1;i--) for(j=1;j<15;j++){ minbox(j*MINBOXSIZE,i*MINBOXSIZE,BGCOLOR,BGCOLOR); gril[i][j]=gril[i-1][j]; if(gril[i][j]==1) minbox(j*MINBOXSIZE,i*MINBOXSIZE,minboxcolor,0); } } /*消掉所有都有最小方块的行*/ void delete(){ int i,j,zero,delgx=0; char *nm="00000"; for(i=1;i<21;i++){ zero=0; for(j=1;j<15;j++) if(gril[i][j]==0) zero=1; if(zero==0){ delcol(i); delgx++; } } num=num+delgx*delgx*10; dj=num/10000; sprintf(nm,"%d",num); clscr(456,173,500,200,4); txt(456,173,"Number:",1,15); txt(456,193,nm,1,15); } /*时钟中断结束*/void KillTimer(){ disable();setvect(TIMER,oldhandler);enable(); } /* 测试当前方块是否可以向下落*/ int downok(){ int i,j,k=1,a[4][4]; for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j] && gril[col+i+1][row+j]) k=0; return(k); } /* 测试当前方块是否可以向左行*/ int leftok(){ int i,j,k=1,a[4][4]; for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j] && gril[col+i][row+j-1]) k=0; return(k); } /* 测试当前方块是否可以向右行*/ int rightok(){ int i,j,k=1,a[4][4]; for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j] && gril[col+i][row+j+1]) k=0; return(k); } /* 测试当前方块是否可以变形*/ int upok(){ int i,j,k=1,a[4][4]; for(i=0;i<4;i++) for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx+1][i]; for(i=3;i>=0;i--) for(j=3;j>=0;j--) if(a[i][j] && gril[col+i][row+j]) k=0; return(k); } /*当前方块落下之后,给屏幕坐标作标记*/ void setgril(){ int i,j,a[4][4]; funbox(0,0,minboxcolor,0); for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j]) gril[col+i][row+j]=1; col=1;row=7; } /*游戏结束*/ void gameover(){ int i,j; for(i=20;i>0;i--) for(j=1;j<15;j++) minbox(j*MINBOXSIZE,i*MINBOXSIZE,2,0); txt(103,203,"Game Over",3,10); } /*按键的设置*/ void call_key(int keyx){ switch(keyx){ case VK_DOWN: { /*下方向键,横坐标加一。
/ if(downok()){ col++; funbox(0,0,minboxcolor,0);} else{ funbox(0,0,minboxcolor,0); setgril(); nextfunbox(NEXTCOL,NEXTROW,4,4); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); delete(); } break; } case VK_UP: { /*上方向键,方向形状旋转90度*/ if(upok()) boxfx++; if(boxfx>3) boxfx=0; funbox(0,0,minboxcolor,0); break; } case VK_LEFT:{ /*左方向键,纵坐标减一*/ if(leftok()) row--; funbox(0,0,minboxcolor,0); break; } case VK_RIGHT:{ /*右方向键,纵坐标加一*/ if(rightok()) row++; funbox(0,0,minboxcolor,0); break; } case VK_SPACE: /*空格键,直接落到最后可以落到的们置*/ while(downok()) col++; funbox(0,0,minboxcolor,0); setgril(); nextfunbox(NEXTCOL,NEXTROW,4,4); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); delete(); break; default: { txt(423,53,"worng key!",1,4); txt(428,80,"Plese Enter Anly Key AG!",1,4); getch(); clscr(420,50,622,97,BGCOLOR); } } } /*时间中断开始*/ void timezd(void){ int key; SetTimer(newhandler); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); for(;;){ if(bioskey(1)){ key=bioskey(0); funbox(0,0,BGCOLOR,BGCOLOR); if(key==VK_ESC) break; call_key(key); } if(TimerCounter>gamedj[dj]){ TimerCounter=0; if(downok()){ funbox(0,0,BGCOLOR,BGCOLOR); col++; funbox(0,0,minboxcolor,0); } else { if(col==1){ gameover(); getch(); break; } setgril(); delete(); funbox(0,0,minboxcolor,0); col=1;row=7; funbox(0,0,BGCOLOR,BGCOLOR); nextfunbox(NEXTCOL,NEXTROW,4,4); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); } } } } /*主程序开始*/ void main(void){ int i,j; char *nm="00000"; init(VGA,VGAHI); cls(); /*屏幕坐标初始化*/ for(i=0;i<=MAXCOL+1;i++) for(j=0;j<=MAXROW+1;j++) gril[i][j]=0; for(i=0;i<=MAXCOL+1;i++) { gril[i][0]=1; gril[i][15]=1; } for(j=1;j<=MAXROW;j++){ gril[0][j]=1; gril[21][j]=1; } clscr(0,0,640,480,15); win(1,1,639,479,4,15); win(SCCOL+MINBOXSIZE-2,SCROW+MINBOXSIZE-2,SCCOL+15*MINBOXSIZE+2,SCROW+21*MINBOXSIZE+2,BGCOLOR,0); nextboxgs=random(8); nextboxfx=random(4); sprintf(nm,"%d",num); txt(456,173,"Number:",1,15); txt(456,193,nm,1,15); txt(456,243,"Next Box:",1,15); timezd(); KillTimer(); closegraph(); } 。