扫雷课程设计报告.doc_第1页
扫雷课程设计报告.doc_第2页
扫雷课程设计报告.doc_第3页
扫雷课程设计报告.doc_第4页
扫雷课程设计报告.doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

湖南文理学院课程设计报告课程名称: 计算机课程扫地雷设计 院 系: 电气与信息工程学院 专业班级: 通信09102班 学生姓名: 孔启浩 指导教师: 完成时间: 2010.9.27 报告成绩: 评阅意见:评阅教师 日期 扫地雷游戏扫地雷游戏设计综述在计算机逐步渗入社会生活各个层面的今天,计算机已经成为人们日常生活的一分,越来越多的人使用计算机办公、娱乐等等。扫雷游戏是Windows操作系统自带的一款小游戏,在过去的几年里,Windows操作系统历经数次换代更新,变得越来越庞大、复杂,功能也越来越强大,但是这款小游戏依然保持原来的容貌,可见这款小游戏受到越来越多人的喜爱。我利用Turbo C 编写了与它功能相仿的扫雷游戏,寓学于乐。一、 应用环境1.1 硬件环境一台完整的电脑,包括键盘、鼠标,最小硬盘空间1GHz1.1 386,486,586及兼容机.640K基本内存;2.1 1M以上扩充内存,10M以上的显示内存.2.2 软件环境开发环境:本系统的设计采用的是TC语言开发Windows 操作系统,Turbo C 2.0汉化版二、 程序的作用及设计目的2.1 程序功能程序的功能是随机生成地雷数,通过鼠标操作玩游戏,不接受键盘,按任意键结束程序。单击屏幕上的笑脸可以重新开始游戏。所有地雷标出后胜利,当鼠标左键单击到地雷时失败。2.2 程序设计目的1培养综合运用所学知识独立完成课题的能力。2更深入地理解和掌握该课程中的有关基本概念,程序设计思想和方法。3提高对工作认真负责、一丝不苟,对同学团结友爱,协作攻关的基本素质。4培养勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论,全方位考虑问题等科学技术人员应具有的素质。5培养从资料文献、科学实验中获得知识的能力,提高从别人经验中找到解决问题的新途径的悟性,初步培养工程意识和创新能力。6对掌握知识的深度、运用理论去处理问题的能力、实验能力、课程设计能力、书面及口头表达能力进行考核。三、 程序分析和设计3.1 游戏规则设计1010 格区域,单击鼠标后,该格显示数字,则表示它周围8 个空格内含有的地雷数,周围没有地雷的显示空白,则不能再单击了。如果是地雷,则游戏结束。如果判断是地雷,可以单击鼠标右键标出,显示红旗,要取消红旗标志则再单击鼠标右键,当所有地雷都标出,每个空格都处理过,了则胜利结束。3.2 游戏界面游戏初始界面如图5-1 所示 , 游戏中的界面如图5-2 所示。 图5-1 初始状态 图5-2 游戏中3.3 设计思路扫雷程序主要用了一个10 行10 列的二维数组表示,数组的每一个元素是结构体类型,结构体中的num 成员代表格内当前处于什么状态,值为1 表示有雷,值为0 表示已经变成空白格或者显示过数字,roundnum 成员统计每个格子周围有多少地雷,flag 变量主要是鼠标右键测试的标志,如果flag 为1 则表示格子显示红旗,这样鼠标左键点在这个格子中将无效。算法的重点是一开始统计好每个格子周围有多少地雷,然后当鼠标左键点在没地雷的格子上时进行两种判断,如果格子周围没地,雷就先在原来的格子位置显示空白格,然后用递归的方法同样判断周围的8 个格子;如果格子周围有地雷,就在该格子上显示具体的雷数。在递归判断8 个格子时,如果格子上有雷或者格子已经显示过雷数或者空白格,以及格子上有红旗标志的话,就不再对格子进行任何判断。具体的函数流程如图5-3 所示1 main()主函数定义使用到的常数、全局变量、函数原型说明。然后初始化图形系统,调用游戏控制函数,游戏只接受鼠标操,作按任意键结束游戏,关闭图形系统,程序结束。2 Control()游戏控制函数调用函数GameBegin()显示游戏初始界面,调用GamePlay()为具体游戏操作过程,该函数返回有两种可能:一种是正在玩中,提前结束游戏;一种是玩完,要么失败,要么胜利。如果是前者,则重新开始游戏,如果是后者,则判断是否单击了笑脸,是则重新开始,否则结束程序。3 GameBegin()画初始界面这个函数完成初始界面的设计以及随机生成地雷数。初始界面的主要工作是确定图的位置和方格显示的位置。外边框的左上角坐标为(190 ,60),右下角坐标为(390, 290),显示笑脸和地雷数的区域为(190, 60)( 390, 90),每个方格的宽度和高度均为16。读者可以参照修改区域的大小。4 DrawSmile()画笑脸利用画椭圆函数fillellipse()和bar()画笑脸,设置好填充模式。5 DrawEmpty()两种格子的显示函数的参数为四个,确定格子的坐标i 和j 、模式和颜色。格子有两种:一种是可以单击的格子;一种是已经显示空白的格子, 比前一种格子略小一些, 通过参数模式和颜色来控制。6 DrawRedflag()显示红旗用单击鼠标右键表示起地雷,起雷后显示一个小红旗。7 GamePlay()游戏过程游戏过程主要是对鼠标按键的处理,具体算法如下:1 统计每个格子周围有多少地雷。2 如果没有按键盘则循环执行;(1)如果单击了鼠标左键则判断:如果鼠标单击了笑脸则游戏重新开始。如果单击了方格,判断该格子里有红旗,则按键无效。如果单击的格子没有显示过数字或空白,则判断;如果是地雷,游戏结束,显示地雷分布;如果不是地雷,则统计该格子周围(8 个方向)的地雷数,如果周围地雷数为0, 调用递归函数ShowWhite()处理周围格子的情况,显示周围地雷数或空白。如果单击的格子周围地雷数不为0, 则显示周围地雷数,将处理过的格子作标记。如果所有格子处理完毕,游戏胜利,显示胜利信息。(2) 如果单击了鼠标右键,该格子没有红旗,则显示红旗。如果有红旗,再击右键,则红旗消失。(3) 重复步骤(2) 直到按键结束程序。8 MineStatistics()统计地雷统计每个格子周围的雷数,分别考虑格子处于四个角、四条边以及中间某个位置的情况。周围指上、下、左、右、左上、左下、右上、右下。注意程序中使用的是多个if 语句,而没有使用或运算连接组成复合表达式,例如:if(Mine01.num=1)nNUM+;if(Mine10.num=1)nNUM+;没有写成if(Mine01.num=1| Mine10.num=1)是考虑到C 语言的逻辑表达式的短路问题,逻辑或只要前面的表达式为真,后面就不必判断了,这样可能造成少计地雷数。9 ShowWhite()显示无雷区的空白格当单击了某个格子,该格子周围地雷数为0 时,应该继续判断它周围8 个方向的格子的周围地雷数是否为0 ,将这些格子都用空白显示。所以这也是一个递归问题,将其构造为递归函数。一个递归函数有两个要素,一个是入口参数,且是降规模的,另一个为出口参数。本函数的入口参数为格子的坐标,表示处理哪个格子,出口参数是该格子有红旗或者已经显示过数字或空白格子。具体算法如下:(1) 如果当前格子有红旗或者已经显示过数字或空白格子,则返回。(2) 空白格子数减1( 统计处理过多少格子)。(3)如果周围的地雷数为0, 且它不是地雷,则将它显示为空白,同时将它的状态值num 置0, 表示处理过;如果周围的地雷数不为0, 显示周围地雷数,同时将它的状态值num 置0 ,表示处理过(即显示过数字),返回。(4) 8 个方向递归调用函数显示所有的空白格子。10 GameOver()游戏失败如果单击了地雷,则地雷爆炸,游戏结束,显示所有的地雷,两重循环判断每个格子的状态,如果状态值为1, 则为地雷,设置红色背景,实体填充模式,画圆表示地雷。11 GameWin()输出最后的胜利者结果如果所有格子都处理过了,就表示胜利,输出you win 信息。12 鼠标处理函数在Windows 应用程序中,人们越来越离不开的输入设备是鼠标,用户拿着鼠标指指点点就完成了几乎全部的工作,利用Visual Basic、 Visual C 等开发工具开发Windows应用程序,系统提供了鼠标支持功能,无须程序员在这方面下功夫。然而在DOS 环境下,用户要使用鼠标必须自己加载鼠标驱动程序。在Windows 操作系统下,系统自动加载了鼠标驱动程序,但并不意味着在任何程序下都可以使用,用Turbo C 开发的应用程序要支持鼠标操作,则必须进行鼠标设备驱动程序的访问。鼠标设备驱动程序的访问通过使用中断0x33 访问。本程序中所用中断0x33 的功能与参数如表5-1 所示。说明该游戏程序在Windows XP 下不支持鼠标。 四、 程序测试及分析4.1程序调试是指对程序的查错和排错。为了便于查错、阅读,在设计该程序的过程中我们采用了结构化程序方法编辑,添加了尽可能多的注释,这就为接下来的调试过程带来了很多方便。4.2经过仔细检查之后进行上机调试。进行编译,如果在编译和连接过程中发现错误,屏幕上显示了出错信息,根据提示找到出错的位置,加以改正,再进行编译如此反复,直到顺利通过编译和连接为止。游戏开始图游戏中 4.3在本次实习过程中碰到的编译、连接的错误主要有:缺少变量定义,定义位置不正确、语法错误、注释的位置等。4.4 错误解决方法。(1)缺少变量定义,定义位置不正确;由于该程序相对来讲稍有些长,前后有些变量不容易联系起来,但是在错误信息的提示下一般还是很容易找到。不过需要注意的是在定义的时候有些函数使用同样的变量名而表示不同的作用,因而使用要很小心,定义及定义的位置要特别留意。为减少这样的错误我后来还是用不同的变量名来表示,结果引起的那些错误解决了。例如: 未定义void Close(void);/*图形关闭*/,所以输出void Close(void);中就有错误,因为缺少定义。(2)语法错误;大多的语法错误在通过书本参考下能够修改。主要是平时缺乏锻炼、不太注意而产生的。如没有注意具体数据使用是有一定的范围限定;过分重视分号的重要性而在for、if、while语句中画蛇添足加分号;在使用文件的时候忘记将文件先打开,对打开的方式(3)注释的位置;程序设计中在注释的时候不能同我们平常写字一样随心所欲,我们应该注意注释的格式。注释中不能含有c语言可执行的语句!五、 心得体会课程设计是本科学习阶段一次非常难得的理论与实际相结合的机会,通过这次比较完整的一个程序的设计,我摆脱了单纯的理论知识学习状态,和实际设计的结合锻炼了我的综合运用所学的基础知识,解决实际问题的能力,同时也提高我查阅文献资料、对程序整体的把握等其他能力水平,而且通过对整体的掌控,对局部的取舍,以及对细节的斟酌处理,都使我的能力得到了锻炼,经验得到了丰富。这是我们都希望看到的也正是我们进行课程设计的目的所在。虽然设计内容繁多,过程繁琐但我的收获却更加丰富。各种组件的运用,各种算法的应用,各种控件的利用我都是随着设计的不断深入而不断熟悉并逐步掌握的。和老师以及同学的沟通交流更使我对程序整体的规划与设计有了新的认识也对自己提出了新的要求。提高是有限的但提高也是全面的,正是这一次设计让我积累了许多实际经验,也必然会让我在未来的工作学习中表现出更高的应变能力和理解力。顺利如期的完成本次课程设计给了我很大的信心,但是也让多不足的地方,学习其实就是一个不断完善的过程,正视自己的不足之处,在以后的工作和学习中不断的弥补这些不足之处,在以后的生活中也要保持同样的态度,不断的完善自己。六、 总结6.1 知识点1 数组的应用。2 全局变量的应用。3 按键的处理。4 递归函数。5 鼠标应用。6.2 功能扩充、修改程序,设初级、中级、高级三个等级,初级地雷数较少,在15 个以内,中级在15 到30 个,高级则扩大棋盘为2020, 地雷数为30 个以上。七、 参考文献7.1 郭翠英主编的C语言课程设计实例精编;7.2 张芳妮 吕波 译C语言编程常见问题解答;7.3 谭浩强C程序设计题解与上机指导(第二版)。7.4 伍俊良.VB课程设计与系统开发案例M.北京:清华大学出版社,2002。附: 源程序#include #include #include #define LEFTPRESS 0xff01#define LEFTCLICK 0xff10#define LEFTDRAG 0xff19#define MOUSEMOVE 0xff08structint num;/*格子当前处于什么状态1 有雷0 已经显示过数字或者空白格子*/int roundnum;/*统计格子周围有多少雷*/int flag;/*右键按下显示红旗的标志0 没有红旗标志1 有红旗标志*/Mine1010;int gameAGAIN=0;/*是否重来的变量*/int gamePLAY=0;/*是否是第一次玩游戏的标志*/int mineNUM;/*统计处理过的格子数*/char randmineNUM3;/*显示数字的字符串*/int Keystate;int MouseExist;int MouseButton;int MouseX;int MouseY;void Init(void);/*图形驱动*/void MouseOn(void);/*鼠标光标显示*/void MouseOff(void);/*鼠标光标隐藏*/void MouseSetXY(int,int);/*设置当前位置*/int LeftPress(void);/*左键按下*/int RightPress(void);/*鼠标右键按下*/void MouseGetXY(void);/*得到当前位置*/void Control(void);/*游戏开始重新关闭*/void GameBegain(void);/*游戏开始画面*/void DrawSmile(void);/*画笑脸*/void DrawRedflag(int,int);/*显示红旗*/void DrawEmpty(int,int,int,int);/*两种空格子的显示*/void GameOver(void);/*游戏结束*/void GameWin(void);/*显示胜利*/int MineStatistics(int,int);/*统计每个格子周围的雷数*/int ShowWhite(int,int);/*显示无雷区的空白部分*/void GamePlay(void);/*游戏过程*/void Close(void);/*图形关闭*/*主函数*/void main(void)Init();Control();Close();void Init(void)/*图形开始*/int gd=DETECT,gm;initgraph(&gd,&gm,c:tc);void Close(void)/*图形关闭*/closegraph();void MouseOn(void)/*鼠标光标显示*/_AX=0x01;geninterrupt(0x33);void MouseOff(void)/*鼠标光标隐藏*/_AX=0x02;geninterrupt(0x33);void MouseSetXY(int x,int y)/*设置当前位置*/_CX=x;_DX=y;_AX=0x04;geninterrupt(0x33);int LeftPress(void)/*鼠标左键按下*/_AX=0x03;geninterrupt(0x33);return(_BX&1);int RightPress(void)/*鼠标右键按下*/_AX=0x03;geninterrupt(0x33);return(_BX&2);void MouseGetXY(void)/*得到当前位置*/_AX=0x03;geninterrupt(0x33);MouseX=_CX;MouseY=_DX;/*游戏开始重新关闭*/void Control(void)int gameFLAG=1;/*游戏失败后判断是否重新开始的标志*/while(1)if(gameFLAG)/*游戏失败后没判断出重新开始或者退出游戏的话就继续判断*/GameBegain(); /*游戏初始画面*/GamePlay();/*具体游戏*/if(gameAGAIN=1)/*游戏中重新开始*/gameAGAIN=0;continue;MouseOn();gameFLAG=0;if(LeftPress()/*判断是否重新开始*/MouseGetXY();if(MouseX280&MouseX65&MouseY85)gameFLAG=1;continue;if(kbhit()/*判断是否按键退出*/break;MouseOff();/*画笑脸*/void DrawSmile(void)setfillstyle(SOLID_FILL,YELLOW);fillellipse(290,75,10,10);setcolor(YELLOW);setfillstyle(SOLID_FILL,BLACK);/*眼睛*/fillellipse(285,75,2,2);fillellipse(295,75,2,2);setcolor(BLACK);/*嘴巴*/bar(287,80,293,81);/*显示红旗*/void DrawRedflag(int i,int j)setcolor(7);setfillstyle(SOLID_FILL,RED);bar(198+j*20,95+i*20,198+j*20+5,95+i*20+5);setcolor(BLACK);line(198+j*20,95+i*20,198+j*20,95+i*20+10);/*两种空格子的显示*/void DrawEmpty(int i,int j,int mode,int color)setcolor(color); setfillstyle(SOLID_FILL,color);if(mode=0)/*没有单击过的大格子*/bar(200+j*20-8,100+i*20-8,200+j*20+8,100+i*20+8);elseif(mode=1)/*单击过后显示空白的小格子*/bar(200+j*20-7,100+i*20-7,200+j*20+7,100+i*20+7);/*游戏开始画面*/void GameBegain(void)int i,j;cleardevice();if(gamePLAY!=1)MouseSetXY(290,70); /*鼠标一开始的位置并作为它的初始坐标*/MouseX=290;MouseY=70;gamePLAY=1;/*下次按重新开始的话鼠标不重新初始化*/mineNUM=0;setfillstyle(SOLID_FILL,7);bar(190,60,390,290);for(i=0;i10;i+)/*画格子*/for(j=0;j10;j+)DrawEmpty(i,j,0,8);setcolor(7);DrawSmile();/*画脸*/randomize();for(i=0;i10;i+)/*100 个格子随机赋值有没有地雷*/for(j=0;j10;j+)Mineij.num=random(8);/*如果随机数的结果是1 表示这个格子有地雷*/if(Mineij.num=1)mineNUM+;/*现有雷数加1*/elseMineij.num=2;Mineij.flag=0;/*表示没红旗标志*/sprintf(randmineNUM,%d,mineNUM); /*显示这次总共有多少雷数*/setcolor(1);settextstyle(0,0,2);outtextxy(210,70,randmineNUM);mineNUM=100-mineNUM;/*变量取空白格数量*/MouseOn();/*游戏结束画面*/void GameOver(void)int i,j;setcolor(0);for(i=0;i10;i+)for(j=0;j10;j+)if(Mineij.num=1)/*显示所有的地雷*/DrawEmpty(i,j,0,RED);setfillstyle(SOLID_FILL,BLACK);fillellipse(200+j*20,100+i*20,7,7);void GameWin(void)/*显示胜利*/setcolor(11);settextstyle(0,0,2);outtextxy(230,30,YOU WIN!);/*统计每个格子周围的雷数*/int MineStatistics(int i,int j)int nNUM=0;if(i=0&j=0)/*左上角格子的统计*/if(Mine01.num=1)nNUM+;if(Mine10.num=1)nNUM+;if(Mine11.num=1)nNUM+;else if(i=0&j=9)/*右上角格子的统计*/if(Mine08.num=1)nNUM+;if(Mine19.num=1)nNUM+;if(Mine18.num=1)nNUM+;else if(i=9&j=0)/*左下角格子的统计*/if(Mine80.num=1)nNUM+;if(Mine91.num=1) nNUM+;if(Mine81.num=1)nNUM+;else if(i=9&j=9)/*右下角格子的统计*/if(Mine98.num=1)nNUM+;if(Mine89.num=1)nNUM+;if(Mine88.num=1)nNUM+;else if(j=0)/*左边第一列格子的统计*/if(Mineij+1.num=1)nNUM+;if(Minei+1j.num=1)nNUM+;if(Minei-1j.num=1)nNUM+;if(Minei-1j+1.num=1)nNUM+;if(Minei+1j+1.num=1)nNUM+;else if(j=9)/*右边第一列格子的统计*/if(Mineij-1.num=1)nNUM+;if(Minei+1j.num=1)nNUM+;if(Minei-1j.num=1)nNUM+;if(Minei-1j-1.num=1)nNUM+;if(Minei+1j-1.num=1)nNUM+;else if(i=0)/*第一行格子的统计*/if(Minei+1j.num=1)nNUM+;if(Mineij-1.num=1)nNUM+;if(Mineij+1.num=1) nNUM+;if(Minei+1j-1.num=1)nNUM+;if(Minei+1j+1.num=1)nNUM+;else if(i=9)/*最后一行格子的统计*/if(Minei-1j.num=1)nNUM+;if(Mineij-1.num=1)nNUM+;if(Mineij+1.num=1)nNUM+;if(Minei-1j-1.num=1)nNUM+;if(Minei-1j+1.num=1)nNUM+;else/*普通格子的统计*/if(Minei-1j.num=1)nNUM+;if(Minei-1j+1.num=1)nNUM+;if(Mineij+1.num=1)nNUM+;if(Minei+1j+1.num=1)nNUM+;if(Minei+1j.num=1)nNUM+;if(Minei+1j-1.num=1)nNUM+;if(Mineij-1.num=1)nNUM+;if(Minei-1j-1.num=1)nNUM+;return(nNUM);/*把格子周围一共有多少雷数的统计结果返回*/*显示无雷区的空白部分*/int ShowWhite(int i,int j)if(Mineij.flag=1|Mineij.num=0)/*如果有红旗或该格处理过就不对该格进行任何判断*/return; mineNUM-;/*显示过数字或者空格的格子就表示多处理了一个格子当所有格子都处理过了表示胜利*/if(Mineij.roundnum=0&Mineij.num!=1)/*显示空格*/DrawEmpty(i,j,1,7);Mineij.num=0;elseif(Mineij.roundnum!=0)/*输出雷数*/DrawEmpty(i,j,0,8);sprintf(randmineNUM,%d,Mineij.roundnum);setcolor(RED);outtextxy(195+j*20,95+i*20,randmineNUM);Mineij.num=0;/*已经输出雷数的格子用0 表示已经用过这个格子*/return;/*8 个方向递归显示所有的空白格子*/if(i!=0&Minei-1j.num!=1)ShowWhite(i-1,j);if(i!=0&j!=9&Minei-1j+1.num!=1)ShowWhite(i-1,j+1);if(j!=9&Mineij+1.num!=1)Show

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论