计算机课程设计 - 俄罗斯方块 - 图文

更新时间:2024-06-20 21:39:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

题 目 : 俄罗斯方块游戏 姓 名 : 学 号 :

院(系): 信息工程学院

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

三、实现的主要功能和系统结构

1、主要功能: 新游戏(newgame): 新游戏流程图: 6

上次游戏(last game): 7

8

排行榜(ranking list): 用绘图函数画出排行榜的界面,然后从文件中读取排行信息,用图形下的文本输出函数outtextxy(int,int,char*)将读取的信息写在屏幕上对应的位置。 详细功能介绍: 首先进行菜单初始化(有绘图函数画出来),默认选中第一项(新游戏);用↑(W)

9

和↓(S)来控制菜单选项。 选中New game(新游戏)后回车,进入新游戏:游戏等级(grade)越高下落速度越快。如下图: 游戏结束提示: 选中“to menu”回车返回游戏菜单,选中“replay”回车重玩游戏。

10

选中“Last game”回车,接着上次的游戏玩。如果没有上次游戏的保存文件(即第一次进入游戏界面)会提示:“Not the last game!”,如下图: 如果上次游戏已经结束会提示:“The last game is over!”,如下图:

11

选中“Ranking list”回车,进入排行榜界面: 12

分数(point)越高(同时对应的等级(grade)也越高)排名越高;分数相同时,消除的总行数越少排名越高。按回车键返回主菜单。 选中“Quit the game”回车退出游戏。

13

2、系统结构: 程序运行后,先进入游戏菜单;当选中“新游戏”、“上次游戏”、或“排行榜”执行时,都会再次返回游戏菜单。只有选中“退出游戏”执行后才能终止程序的运行。 14

四、核心算法描述和相关技术说明

1、核心算法描述: 这里把游戏的关键设计放在三个盒子和一个坐标上: 大盒子:一个二维数组zxp[23][10](前三行不在屏幕上显示),记录着主游戏区方块点阵的开与关(把主游戏区想像成一个点阵)。 两个4*4小盒子:两个二维数组,一个盛放着正在下落的方块(小盒子2),一个盛放着预览区的方块(小盒子1),当然这两个也必须想像成一个点阵:如长条 的点阵为: 0100 0100 0100 0100 现在只要有这么一个概念:随即拿出一种方块放在小盒子1里,将小盒子1里的方块放到小盒子2里,再随即拿出一种方块放在小盒子1里,不断定时下落的小盒子2从大盒子顶部下降到底部,之后再进行下一轮的下落... 中间再加一些控制即可。 下落的小盒子2和主游戏区点阵之间的联系: 定义一个坐标:x,y,保存着小盒子2左上角在主游戏区点阵上对应的下标(位置),即当x = 0, y = 0时,小盒子2处于点阵的左上部.如此,当小盒子2需要移动时,即只须要改变x,y的值. 判断碰撞: 通常这种情况只须要在有移动小盒子2或旋转小盒子2时发生:也即点阵非空与空是互斥的,当小盒要向下移(y++)时,如果小盒子2里的点阵与主游戏去上的点阵(非空的地方)重叠,则不能下移,(卡住了),旋转则转换后的形状与主游戏区有冲突则要放弃旋转. 2、相关技术说明: 用到的语言(C语言)说明: C语言是由UNIX的研制者丹尼斯·里奇(Dennis Ritchie)和肯·汤普逊(Ken Thompson)于1970年研制出的B语言的基础上发展和完善起来的。C语言,是一种通用的、过程式的编程语言,广泛用于系统与应用软件的开发。具有高效、灵活、功能丰富、表达力强和较高的移植性等特点,在程序员中备受青睐。根据游戏设计复杂度不高、编码工作量不大等特点,程序开发语言选择简洁、高效、灵活的C语言。 用到编译器(turbo c2.0)说明: turbo c 2.0 是Borland公司为PC系列微型计算机研制的C语言编译软件包,功能相当完善。特别是它的集成工作环境,可以用来完成编辑、编译、连接、调试和运行一个程序而不必脱离Turbo C 环境。这种功能既方便用户使用,又使文件编译时间大大缩短,提高了软件生成、调试和检测的速度,成为微型计算机

15

上最流行的C语言编译器之一。 TURBO C 2.0版编程环境的一个主要缺点是不支持鼠标操作,也不能同时编辑多个文件。

五、总结和体会

俄罗斯方块曾在童年时代给了我无尽的快乐,而现在我又亲自用自己的知识制作了一个俄罗斯方块的软件,这使我很有成就感。编写软件使我提高了很多很多,相比以前我更加耐心、细心了,在思维的方面也更加周全了。 同时,我也发现了自己的缺点和不足之处,在遇到问题的时候我 缺乏一个编程人员应有的沉着和冷静,不能够立即进行思考。相信更多的磨练会让我的意志更加坚定,思维更加活跃和全面。 在此,我要感谢我的团队的其他成员,正是有了他们,我们的团队才能够圆满的完成任务。

16

源代码: #include #include #include #include #include #define MBKCOLOR 15 /*主菜单背景颜色*/ #define GNAMECOLOR RED /*游戏名字颜色*/ #define CCOLOR1 GREEN /*主菜单选项条的颜色*/ #define CCOLOR2 15 /*主菜单选项条上字体的颜色*/ #define SIGNCOLOR RED /*主菜单选项条别选中后的颜色*/ #define BKCOLOR LIGHTGRAY /*游戏背景颜色*/ #define BKCOLOR1 15 /*主显屏周围的颜色*/ #define KCOLOR RED /*游戏边框颜色*/ #define PRE_COLOR GREEN / *预览区颜色*/ #define GLP_COLOR GREEN /*游戏成绩颜色*/ #define EXPL_COLOR RED /*游戏提示颜色*/ #define BT1_COLOR YELLOW /*第一类方块的颜色*/ #define BT2_COLOR GREEN /*第二类方块的颜色*/ #define BT3_COLOR BROWN /*第三类方块的颜色*/ #define BT4_COLOR LIGHTRED /*第四类方块的颜色*/ #define BT5_COLOR BLUE /*第五类方块的颜色*/ #define BT6_COLOR RED /*第六类方块的颜色*/ #define BT7_COLOR MAGENTA /*第七类方块的颜色*/ #define DELLCOLOR 15 /*需删除的行将要消失时的颜色*/ #define DCOLOR DARKGRAY /*游戏结束时弹出的窗口的颜色*/ #define OGCOLOR RED /*游戏结束提示字体的颜色*/ #define DGLPCOLOR GREEN /*游戏结束时窗口中显示的成绩的颜色*/ #define DCCOLOR1 DARKGRAY /*游戏结束时窗口选项条的颜色*/ #define DCCOLOR2 15 /*游戏结束时窗口选项条中字体的颜色*/ #define DSIGNCOLOR LIGHTGRAY /*游戏结束时窗口选项条被选中后的颜色*/ #define NCOLOR DARKGRAY /*没有上次游戏时弹出的窗口的颜色*/ #define NTLGCOLOR RED /*没有上次游戏时窗口中提示字体的颜色*/ #define NCOLOR1 LIGHTGRAY /*没有上次游戏时窗口确定条的颜色*/ #define NCOLOR2 15 /*没有上次游戏时窗口确定条里字体的颜色*/ #define RBKCOLOR DARKGRAY /*排行榜背景颜色*/ #define RLINECOLOR GREEN /*排行榜线框颜色*/ #define RCHCOLOR RED /*排行榜标题颜色*/ #define RLKCOLOR1 DARKGRAY /*排行榜前三名数字的颜色*/ #define RLKCOLOR2 15 /*排行榜后七名数字的颜色*/ #define ROKCOLOR1 LIGHTGRAY /*排行榜确定条的颜色*/ #define ROKCOLOR2 15 /*排行榜确定条内字体的颜色*/ #define RGLPCOLOR 15 /*排行榜每行游戏成绩的颜色*/ struct rlist

17

{ int rgrade; int rlnum; int rpoint; }rl[10]; /*记录游戏得分前十名的成绩*/ struct blocktype { int bktp[4][4]; int color; }bt[19]; /*记录所有方块的形状(共19种)及颜色*/ struct p_ztemp { int x,y,bp[4][4]; int color; }tempbt; /*在预览区与游戏窗口(主显屏)之间做缓冲存储*/ int zxp[23][10],zxpcolor[23][10]; /*记录游戏窗口信息,共20行,10列,前3行为玩家多提 供些操作时间*/ int delline[4]={0}; /*记录需要删除的行*/ struct blocktype pre; /*记录预览区方块信息*/ unsigned int grade=0,lnum=0,point=0; /*记录游戏成绩*/ void initzxp(void); int menu(void); void initmenu(void); void choosecard(int,int,int,char*); void newgame(void); void lastgame(void); void ran_list(void); void initgame(void); void initbt(void); int randompre(void); void pretozxp(int); void pretotemp(int); void temptozxp(void); void refresh(void); void refzxp(void); void refpre(void); void hfk(int,int,int,int,int); void refgmglp(void); int judgedown(int); int judgedel(void); void delfun(void); void ash_down(void); void amark(int *); int judgegm(void);

18

int gamedead(void); void saveran(void); void insertrldata(void); void tofile(void); void replay(int *); void savelast(int,int,int); void initdcard(void); void dchoosecard(int,int,int,char*); void clrzxpbt(void); void bktps_down(void); void initbt0(void); void initbt1(int); void initbt2(int); void initbt3(int); void initbt4(int); void initbt5(int); void initbt6(int); void initbt7(int); int gamehandle(int*,int*); int judgeleft(int); void bktps_left(void); int judgeright(int); void bktps_right(void); int judgeturn(int); void bktps_turn(int*,int); void turntotemp(int); int getlastdata(int *,int *); void nolastgame(char *); void initranlist(void); int getrlistdata(void); void outrldata(void); int main() { int wich; int gdirve=DETECT,gmode; initgraph(&gdirve,&gmode,\ initzxp(); while(1) { wich=menu(); switch(wich) { case 0: newgame(); /*新游戏*/

19

cleardevice(); break; case 1: lastgame(); /*上次游戏*/ cleardevice(); break; case 2: ran_list(); /*排行榜*/ cleardevice(); break; case 3: closegraph(); return 0; /*退出游戏*/ default: ; } } } void initzxp(void) { int i,j; for(i=0;i<24;i++) for(j=0;j<10;j++) { zxp[i][j]=0; zxpcolor[i][j]=BKCOLOR; } return; } int menu(void) { char ch,*mar[4]={\ New game \ Last game \ /*初始化选项卡里面的内容*/ int wich=0; /*刚进入菜单时,指向 \新游戏(New game)\ initmenu(); choosecard(0,SIGNCOLOR,CCOLOR2,mar[0]); while(1) { ch=getche(); switch(ch) { case 'W': case 'w': case 72: choosecard(wich,CCOLOR1,CCOLOR2,mar[wich]);

20

} void initbt5(int bt_color) /*初始化 \ # \ # \{ /* # ### # # */ int i; /* # ## */ for(i=0;i<3;i++) { bt[7].bktp[i][2]=1; bt[8].bktp[2][i+1]=1; bt[9].bktp[i][1]=1; bt[10].bktp[1][i+1]=1; } bt[7].bktp[0][1]=1; bt[8].bktp[1][3]=1; bt[9].bktp[2][2]=1; bt[10].bktp[2][1]=1; bt[7].color=bt_color; bt[8].color=bt_color; bt[9].color=bt_color; bt[10].color=bt_color; return; } void initbt6(int bt_color) /*初始化 \ # \ \ ## \ ### \{ /* # ### # # */ int i; /* ## # */ for(i=0;i<3;i++) { bt[11].bktp[i][2]=1; bt[12].bktp[2][i]=1; bt[13].bktp[i][1]=1; bt[14].bktp[1][i]=1; } bt[11].bktp[2][1]=1; bt[12].bktp[1][0]=1; bt[13].bktp[0][2]=1; bt[14].bktp[2][2]=1; bt[11].color=bt_color; bt[12].color=bt_color; bt[13].color=bt_color; bt[14].color=bt_color; return; } void initbt7(int bt_color) { int i;

26

for(i=0;i<3;i++) { /*初始化 \ # \ # \ ### \ # \ bt[15].bktp[2][i+1]=1; /* ### ## # ## */ bt[16].bktp[i][2]=1; /* # # */ bt[17].bktp[1][i+1]=1; bt[18].bktp[i][2]=1; } bt[15].bktp[1][2]=1; bt[16].bktp[1][3]=1; bt[17].bktp[2][2]=1; bt[18].bktp[1][1]=1; bt[15].color=bt_color; bt[16].color=bt_color; bt[17].color=bt_color; bt[18].color=bt_color; return; } int randompre(void) /*随机产生一个方块形状到预览区,并记录下方块形状的下标*/ { int btnum; srand(time(NULL)); btnum=rand(); pre=bt[btnum]; return btnum; } void pretozxp(int btnum) { pretotemp(btnum); temptozxp(); return; } void pretotemp(int btnum) /*将预览区的方块信息传给\其中的\记录方块的位置*/ { int i,j; for(i=0;i<4;i++) { for(j=0;j<4;j++) { tempbt.bp[i][j]=bt[btnum].bktp[i][j]; } } tempbt.color=bt[btnum].color; tempbt.y=0;

27

tempbt.x=3; } void temptozxp(void) /*将\中的信息显示到游戏窗口*/ { int i,j; for(i=tempbt.y;i

28

for(j=0;j<4;j++) { if(pre.bktp[i][j]) hfk(441,71,i,j,pre.color); } } return; } void hfk(int x0,int y0,int i,int j,int color) /*画一个color颜色的方块*/ { setcolor(color); setfillstyle(1,color); bar(j*20+x0,i*20+y0,j*20+x0+18,i*20+y0+18); return; } void refgmglp(void) { char gstr[20],lstr[20],pstr[20]; setfillstyle(1,BKCOLOR1); bar(436,200,600,450); sprintf(gstr,\ sprintf(lstr,\ sprintf(pstr,\ setcolor(GLP_COLOR); outtextxy(436,200,gstr); outtextxy(436,300,lstr); outtextxy(436,400,pstr); return; } int judgedown(int btnum) { int j; switch(btnum) { case 0: case 8: case 9: case 11: case 12: case 15: /*第0,8,9,11,12,15方块形状只需判断tempbt的第三行为1的下方 对应的游戏窗口位置是否为1 */ if(20==tempbt.y) /*以及tempbt的第三行是否到了最底行*/ return 1; for(j=0;j<4;j++)

29

if(tempbt.bp[2][j]&&zxp[tempbt.y+3][tempbt.x+j]) return 1; break; case 1: case 19: if(19==tempbt.y) /*方法同上*/ return 1; for(j=1;j<3;j++) if(tempbt.bp[3][j]&&zxp[tempbt.y+4][tempbt.x+j]) return 1; if(tempbt.bp[0][0]&&zxp[tempbt.y+1][tempbt.x]||tempbt.bp[0][3]&& zxp[tempbt.y+1][tempbt.x+3]) return 1; break; case 2: /*方法同上*/ if(20==tempbt.y) return 1; for(j=0;j<4;j++) if(zxp[tempbt.y+3][tempbt.x+j]) return 1; break; case 3: case 10: if(20==tempbt.y) return 1; if(zxp[tempbt.y+3][tempbt.x+1]||zxp[tempbt.y+2][tempbt.x+2]||tempbt.bp[1][3] &&zxp[tempbt.y+2][tempbt.x+3]) return 1; break; case 4: case 6: if(20==tempbt.y||tempbt.bp[1][0]&&zxp[tempbt.y+2][tempbt.x]||tempbt.bp[1][3] &&zxp[tempbt.y+2][tempbt.x+3]) return 1; for(j=1;j<3;j++) if(zxp[tempbt.y+3][tempbt.x+j]) return 1; break; case 5: case 14: case 18: if(20==tempbt.y) return 1; for(j=0;j<2;j++)

30

if(tempbt.bp[1][j]&&zxp[tempbt.y+2][tempbt.x+j]||zxp[tempbt.y+3][tempbt.x+2]) return 1; break; case 7: case 16: if(20==tempbt.y||zxp[tempbt.y+3][tempbt.x+2]||tempbt.bp[0][1]&& zxp[tempbt.y+1][tempbt.x+1]||tempbt.bp[1][3]&&zxp[tempbt.y+2][tempbt.x+3]) return 1; break; case 13: if(20==tempbt.y||zxp[tempbt.y+3][tempbt.x+1]||zxp[tempbt.y+1][tempbt.x+2]) return 1; break; case 17: if(20==tempbt.y||zxp[tempbt.y+2][tempbt.x+1]||zxp[tempbt.y+3][tempbt.x+2]|| zxp[tempbt.y+2][tempbt.x+3]) return 1; break; } return 0; /*没有到底部且没有遇到障碍物*/ } int judgedel(void) { int i,j,count=0; for(i=tempbt.y;i

31

if(delline[i]) { for(j=0;j<10;j++) { zxp[tempbt.y+i][j]=0; zxpcolor[tempbt.y+i][j]=DELLCOLOR; } } } return; } void ash_down(void) { int i,j,n; for(n=0;n<4;n++) if(delline[n]) { for(i=tempbt.y+n;i>3;i--) for(j=0;j<10;j++) { zxp[i][j]=zxp[i-1][j]; zxpcolor[i][j]=zxpcolor[i-1][j]; } } return; } void amark(int *pdnum) { switch(*pdnum) { case 1: point+=100; break; case 2: point+=300; break; case 3: point+=600; break; case 4: point+=1000; break; /*每次消行越多,平均每行给的分越高*/ } *pdnum=0; /*用完后值零,为下次再用做好准备*/

32

return; } int judgegm(void) { int j; for(j=0;j<10;j++) if(zxp[3][j]) /*如果游戏窗口第一行有方块说明游戏结束*/ return 1; return 0; } int gamedead(void) { char *dar[2]={\ char wich,ch; initdcard(); /*初始化游戏结束时的界面*/ wich=0; dchoosecard(0,DSIGNCOLOR,DCCOLOR2,dar[0]); /*刚进入界面时,指向第一 个选项(to menu)*/ while(1) { ch=getch(); switch(ch) { case 'D': case 'd': case 77: if(1!=wich) /*条件满足,表示可以向右选*/ { dchoosecard(0,DCCOLOR1,DCCOLOR2,dar[0]); /*首先把左边的选项回复为未选中*/ dchoosecard(1,DSIGNCOLOR,DCCOLOR2,dar[1]); /*然后把右边的选项标记为 选中*/ wich=1; } break; case 'A': case 'a': case 75: if(0!=wich) /*条件满足,表示可以向左选*/ { dchoosecard(1,DCCOLOR1,DCCOLOR2,dar[1]); /*首先把右边的选项回复为未选中*/ dchoosecard(0,DSIGNCOLOR,DCCOLOR2,dar[0]); /*然后把左边的选项标记为 选中*/

33

wich=0; } break; case 13: return wich; } } } void initdcard(void) { char gradear[20],pointar[20],lnumar[20]; char *dar[2]={\ setbkcolor(LIGHTGRAY); setcolor(DCOLOR); setfillstyle(1,DCOLOR); line(169,89,469,89); line(169,389,469,389); line(119,139,119,339); line(519,139,519,339); pieslice(169,139,90,180,50); pieslice(469,139,0,90,50); pieslice(469,339,0,360,50); pieslice(169,339,180,270,50); floodfill(319,239,DCOLOR); /*画出游戏结束时的窗口*/ setcolor(OGCOLOR); settextstyle(1,0,6); outtextxy(177,122,\ /*提示游戏结束*/ sprintf(gradear,\ sprintf(lnumar,\ sprintf(pointar,\ setcolor(DGLPCOLOR); settextstyle(1,0,3); outtextxy(177,200,gradear); outtextxy(177,240,lnumar); outtextxy(177,280,pointar); /*显示游戏结束时的成绩*/ dchoosecard(0,DCCOLOR1,DCCOLOR2,dar[0]); dchoosecard(1,DCCOLOR1,DCCOLOR2,dar[1]); /*画出游戏结束时的两个选项*/ return; } void dchoosecard(int i,int color1,int color2,char *ar) { setcolor(color1); setfillstyle(1,color1); bar(187+i*204,332,247+i*204,362);

34

pieslice(187+i*204,347,90,270,15); pieslice(247+i*204,347,0,360,15); setcolor(color2); settextstyle(2,0,6); outtextxy(186+i*209,337,ar); } void saveran(void) { if(getrlistdata()) /*getrlistdata()返回1说明读取信息失败*/ return; insertrldata(); /*把本次游戏信息按顺序插入到排行榜*/ tofile(); /*将排行数据写到文件里*/ return; } void insertrldata(void) { int i,j; for(i=0;i<10;i++) { if(point>rl[i].rpoint) /*分数越高排名越靠前*/ break; else if(point==rl[i].rpoint) { if(lnumi;j--) rl[j]=rl[j-1]; rl[i].rgrade=grade; rl[i].rlnum=lnum; rl[i].rpoint=point; } return; } void tofile(void) { FILE *fp; if((fp=fopen(\ return; fwrite(rl,sizeof(struct rlist),10,fp); fclose(fp);

35

return; } void replay(int *pbtnum1) { cleardevice(); initzxp(); grade=lnum=point=0; /*重玩只需将游戏成绩归零即可*/ initgame(); *pbtnum1=randompre(); /*随机产生一个方块形状到预览区*/ pretozxp(*pbtnum1); /*将预览区的方块形状传到游戏窗口*/ return; } void savelast(int btnum1,int btnum2,int x) { struct { int sign; /*通过sign来标记上次游戏是否已经结束*/ int sbtnum1,sbtnum2; int szxp[23][10],szxpcolor[23][10]; struct p_ztemp stempbt; int sgrade,slnum; unsigned int spoint; }lastdata; /*用该结构体临时存储上次游戏信息*/ int i,j; FILE *fp; lastdata.sign=x; /*x为1代表上次游戏结束,为0代表上次游戏没有结束*/ for(i=0;i<23;i++) for(j=0;j<10;j++) { lastdata.szxp[i][j]=zxp[i][j]; lastdata.szxpcolor[i][j]=zxpcolor[i][j]; } lastdata.sbtnum1=btnum1; lastdata.sbtnum2=btnum2; lastdata.stempbt=tempbt; lastdata.sgrade=grade; lastdata.slnum=lnum; lastdata.spoint=point; if((fp=fopen(\ /*新建文件 lastgame.txt */ return; fwrite(&lastdata,sizeof(lastdata),1,fp); /*将上次游戏信息写在该文件里*/ fclose(fp); return; }

36

int gamehandle(int *pbtnum1,int *pbtnum2) { int dnum=0,turnnum; /*dnum记录一次消的行数,turnnum记录旋转类型*/ char ch; ch=getche(); switch(ch) { case 'Q': case 'q': ch=getch(); while('Q'!=ch&&'q'!=ch) /*当ch为\或 \时终止循环(结束暂停)*/ { ch=getch(); } break; case 'S': case 's': case 80: if(judgedown(*pbtnum1)) { dnum=judgedel(); /*判断是否有需要消行的 */ if(dnum) { delfun(); /*消除需要删除的行*/ refzxp(); delay(30000); ash_down(); /*需删除行以上的所有行整体下移*/ lnum+=dnum; amark(&dnum); /*根据一次消除的行数进行加分*/ grade=point/5000; /*每5000分一个等级*/ delline[0]=delline[1]=delline[2]=delline[3]=0; /*用过后归零*/ } *pbtnum1=*pbtnum2; pretozxp(*pbtnum1); *pbtnum2=randompre(); refresh(); } else { clrzxpbt(); bktps_down(); /*方块形状向下移动,以实现加速*/ refzxp(); } break;

37

case 'A': case 'a': case 75: if(judgeleft(*pbtnum1)) { clrzxpbt(); bktps_left(); /*方块形状向左移动*/ refzxp(); } break; case 'D': case 'd': case 77: if(judgeright(*pbtnum1)) { clrzxpbt(); bktps_right(); /*方块形状向右移动*/ refzxp(); } break; case 'W': case 'w': case 72: turnnum=judgeturn(*pbtnum1); if(turnnum) { clrzxpbt(); bktps_turn(pbtnum1,turnnum); /*方块形状翻转*/ turntotemp(*pbtnum1); temptozxp(); /*将缓冲区(tempbt)中的信息传到主显屏*/ refzxp(); } break; case 27: /*按\建返回到菜单*/ savelast(*pbtnum1,*pbtnum2,0); /*上次游戏还没有结束*/ return 1; default: ; } return 0; } void bktps_down(void) { tempbt.y++; temptozxp(); /*将缓冲区(tempbt)中的信息传到主显屏*/

38

return; } void clrzxpbt(void) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) if(tempbt.bp[i][j]) { zxp[tempbt.y+i][tempbt.x+j]=0; zxpcolor[tempbt.y+i][tempbt.x+j]=BKCOLOR; } return; } int judgeleft(int btnum) /*方法同下移判断 */ { int i; switch(btnum) { case 0: case 1: case 9: case 10: case 13: if(-1==tempbt.x) return 0; /*x为-1时,方块形状到了最左边*/ for(i=0;i<4;i++) if(tempbt.bp[i][1]&&zxp[tempbt.y+i][tempbt.x]) return 0; break; case 19: if(0==tempbt.x||zxp[tempbt.y][tempbt.x-1]) return 0; /*x为0时,方块形状到了最左边 */ for(i=1;i<4;i++) if(zxp[tempbt.y+i][tempbt.x]) return 0; break; case 2: case 12: if(0==tempbt.x||zxp[tempbt.y+2][tempbt.x-1]) return 0; /*x为0时,方块形状到了最左边 */ if(tempbt.bp[1][0]&&zxp[tempbt.y+1][tempbt.x-1]) return 0; break;

39

case 3: case 5: if(-1==tempbt.x||tempbt.bp[0][2]&&zxp[tempbt.y][tempbt.x+1]|| tempbt.bp[2][2]&&zxp[tempbt.y+2][tempbt.x+1]) return 0; for(i=0;i<3;i++) if(tempbt.bp[i][1]&&zxp[tempbt.y+i][tempbt.x]) return 0; break; case 4: if(0==tempbt.x||zxp[tempbt.y+1][tempbt.x-1]||zxp[tempbt.y+2][tempbt.x]) return 0; break; case 6: case 15: if(-1==tempbt.x||zxp[tempbt.y+1][tempbt.x+1]||zxp[tempbt.y+2][tempbt.x]) return 0; break; case 7: if(-1==tempbt.x||zxp[tempbt.y][tempbt.x]||zxp[tempbt.y+1][tempbt.x+1]|| zxp[tempbt.y+2][tempbt.x+1]) return 0; break; case 8: if(-1==tempbt.x||zxp[tempbt.y+1][tempbt.x+2]||zxp[tempbt.y+2][tempbt.x]) return 0; break; case 11: if(-1==tempbt.x||zxp[tempbt.y][tempbt.x+1]||zxp[tempbt.y+1][tempbt.x+1]|| zxp[tempbt.y+2][tempbt.x]) return 0; break; case 14: if(0==tempbt.x||zxp[tempbt.y+1][tempbt.x-1]||zxp[tempbt.y+2][tempbt.x+1]) return 0; break; case 16: if(-2==tempbt.x) /*x为-2时,方块形状到了最左边*/ return 0; for(i=0;i<3;i++) if(zxp[tempbt.y+i][tempbt.x+1]) return 0; break; case 17:

40

本文来源:https://www.bwwdw.com/article/n6m3.html

Top