布雷程序的实现.docx_第1页
布雷程序的实现.docx_第2页
布雷程序的实现.docx_第3页
布雷程序的实现.docx_第4页
布雷程序的实现.docx_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

布雷程序的实现一:游戏说明。(1)允许用户输入地图的大小,现在用条件所给的9*9。(2)地图中的地雷个数允许用户输入,在地图上的分布是随机的。(3)初始时显示地图,确保每个位置都没有标记。(4)开始玩游戏时,用户每次操作时从键盘上输入3个数据:x,y和op。(x,y)表示操作的位置,字符op表示要执行的操作。点开用“.”表示;标记地雷用“!”表示;取消标记地雷用“c”表示;退出游戏用“q”表示。(5)游戏开始时,踩到地雷则结束游戏,当标记出来的每个地雷位置与实际的位置一样,并且标记出来的地雷个数跟实际地雷个数一样则游戏成功完成。(6)没执行一次操作后,显示操作后的地图。二:地图的表示和输出。 地图我们可以用一组二维数组来表示,如下。.(1) 如果点开的位置的8个相邻位置上都没有地雷,则自动点开一片连续的没有地雷的区域。当有个位置有地雷时,则其周边一定有相应的数字表示周围有多少地雷。即构不成零位置,不能再点开。但该数字被点开。(2) 在程序中,我们用二维数组map来表示这个地图,为了与生活中的习惯一致,我们不用二维数组map中的第0行和第0列元素。而且在计算每个位置周围8个相邻位置上的地雷个数时,不需要再判断该位置是否为第0行或第0列。所以从第1行,第1列开始计算的话,地图中的每个位置的8个相邻位置都是在二维数组范围内,可以统一处理。而不用专门去处理左边界和上边界的位置。同样的道理,在处理右边界和下边界也是一样,我们只需再增加第N+1行和第N+1列就可以了。因此如果最大的地图为9*9,则二维数组map需定义成11*11。(3) Map数组中各元素mapxy的取值及其含义为:-1:(x,y)位置为地雷;08:(x,y)位置上没有地雷,该数字为8个相邻位置上地雷的个数。(4) 那么我们如何表示一个位置的8个相邻位置呢?如图:在(x,y)位置上的左上角位置,其行坐标为x-1,列坐标为y-1,行,列坐标的增量均为-1.右边位置相对于(x,y)位置,行,列坐标的增量分别为0和1。因此在程序中可以定义一个8*2的二维数组dir,表示8个相邻位置的行,列坐标相对于(x,y)位置行,列坐标的增量。注意dir数组所表示的8个位置的顺序是按顺时针从左上角位置开始的。有了这个二维数组,统计(x,y)位置的8个相邻位置上地雷的个数就变得方便多了,我们可以用下面的代码:int k,mines=0;for(k=0;k8;k+) If(mapx+dirk0y+dirk1=-1) mines+;()那么怎样才能把地图输出来呢?在字符界面我们可以用“|”和“_”来构造框架,形象的把地图表示出来。对于N*N的地图,共输出N行。如下图:具体代码如下:void out_map()int i,j;line0=40; for(i=1;i=4*N-1;i+) linei=_; linei=0; puts(line); for(i=1;i=N;i+) line0=|; for(j=1;j=N;j+) line4*j-3=_; if(mapij=-1)line4*j-2=*; else line4*j-2=48+mapij;line4*j-1=_; line4*j=|; line4*N+1=0; puts(line); 注意:第行除了第一个字符是空格字符外,还有N个下划线“”,最后结束标志是;因为输出的是对应的数字字符,所以需要在数字字符“”的编码值的基础上加上的值,最后显示出来的才是希望的结果。三:地雷的随机生成如果地雷是手动设置,那这个游戏就没有可重复性,就没有玩的可能了,所以地雷的位置必须是随机的,这儿引人一个随机函数rand(),它包含在头文件中。该函数用于长生0到RAND_MAX之间的伪随机数。为了保证每次运行程序时产生的随机数不同,所以在rand()函数前,需要调用srand()函数设置随机数种子。该函数的原型为:Void srand(unsigned int seed);所以在调用该函数形式为:Srand(unsigned)time(0);即用当前系统时间作为随机种子,其中time函数是头文件中定义的函数,用于获取当前系统时间。解决了随机数的生成的问题,现在来考虑随机地图的生成。要随机地生成地图,需要随机地生成minenum个地雷的位置(num1,num2),这个位置的行坐标num1和列坐标num2都是1N的随机数。而且minenum个位置不能重复,而为了随机产生一对1N之间的随机数,需做些改动:num1=1+int(1.0*N*rand()/(RAND_MAX+1);num2=1+int(1.0*N*rand()/(RAND_MAX+1);当生成一对随机数(num1,num2)后,还得判断mapnum1num2是否为-1,如果为-1表示之前已经在该位置上设置了地雷,需要重新生成一对随机数。void random_map()int i=1,j,k;srand(unsigned)time(0);int num1,num2;while(i=minenum)num1=1+(int)(1.0*N*rand()/(RAND_MAX+1);/产生1N之间的随机数;num2=1+(int)(1.0*N*rand()/(RAND_MAX+1);/产生1N之间的随机数;if(num1N|num2N|mapnum1num2=-1) /排除第0行和第0列,及重复的地雷位置continue;mapnum1num2=-1;i+;int mines; /对于其余位置统计其周围8个位置上地雷的个数for(i=1;i=N;i+)for(j=1;j=N;j+)if(mapij=-1)continue;mines=0;for(k=0;k8;k+)if(mapi+dirk0j+dirk1=-1)mines+;mapij=mines;四:游戏的实现(1): 在玩游戏时不仅要有生成的游戏地图,还要有玩家的操作地图,通过这个地图我们就可以控制和确定游戏是否结束等等了。这个地图也是用一个二维数组user_map来记录。该数组中的各元素user_mapxy的取值及含义分别为:0:表示用户还没有点开(x,y)位置;1:表示用户已经点开(x,y)位置;2:表示用户已经将(x,y)位置标记为地雷。下面来看看map数组和user_map数组的关系和区别:(a) 实际的地图(b) 对应的map二维数组 (c)显示给用户看的地图(c) 对应的user_map二维数组注:有颜色部分表示数组中没用到的该游戏的地图如同(a)所示,地图中有三个地雷,map数组各元素的值如图(b),map数组各元素的值在游戏过程中是始终不变的。当点开一片连续的空白区域且正确的标记地雷后,user_map数组各元素的值如图(d),显示给用户看到的是地图(c)。(2) 了解用户地图后,现在我们可以考虑怎么输出了。和前面map输出一样,user_map也是同样的道理,只不过输出时要做些变化。而且可以判断游戏是否成功结束,即能判断用户标记的每个地雷位置是否跟实际地雷的位置吻合,并且正确标记出的地雷个数跟地图中地雷的总个数是否相等,如果相等,则游戏成功结束。游戏成功时,把没有点开的位置全部点开。(3) 没操作一次,都要重新显示地图,所以每次都要调用out_user_map函数。函数代码如下:void out_user_map()rightmarknum=0;int i,j;for(i=1;i=N;i+)for(j=1;j=N;j+)if(user_mapij=2&mapij=-1)rightmarknum+;if(rightmarknum=minenum)/用于显示所有还未打开的地图k=true;for(i=1;i=N;i+)for(j=1;j=N;j+)if(user_mapij=0)user_mapij=1;/显示地图: line0=40; for(i=1;i=4*N-1;i+) linei=_; linei=0; puts(line); for(i=1;i=N;i+) line0=|; for(j=1;j=N;j+) line4*j-3=_; if(user_mapij=0)line4*j-2=_; else if (user_mapij=1)line4*j-2=48+mapij; else if (user_mapij=2)line4*j-2=!;line4*j-1=_; line4*j=|; line4*N+1=0; puts(line); (4) 解决了用户地图的输出问题,现在我们就只有考虑最麻烦的一步了。那就是如何点开一片连续的没有地雷的区域。说它麻烦是因为这儿用到了循环算法,用到的函数search().函数原型为: Void search(int x, int y);其中参数x,y表示要点开的位置。如果点开的位置是一个零位置,则调用search()函数,search()函数自动点开周围连续的零位置及他们相邻的位置。具体代码如下:void search(int x,int y)user_mapxy=1; /标记点开(x,y)位置int dx,dy;for(int i=0;i8;i+) /是否点开周围的8个位置dx=x+diri0;dy=y+diri1;if(dxN|dyN)continue;else if(mapdxdy!=0)user_mapdxdy=1;else if(mapdxdy=0&user_mapdxdy=0) /如果(x,y)周围相邻位置没有地雷,且也没有被点开过,则沿着这些位置递归地点开search(dx,dy);(5) 有了上面的准备,我们就可以玩游戏了,我们可以统一在一个函数里完成,这儿我们生成一个playgame(),在该函数中,所有的操作都是在永真循环内执行的,只有当用户请求退出游戏,踩到地雷,或游戏成功结束时才能退出永真循环,下面是具体的代码:void playgame()out_user_map();int x,y;char op;printf(Start Game n);while(1)printf(请输入执行操作的位置及要执行的操作:n);scanf(%d %d %c,&x,&y,&op);if(x=0&y=0&op=p)printf(用户请求退出程序n);break;else if(user_mapxy=1|user_mapxy=2)&op!=c)printf(该坐标也被点开或已被标记为地雷,请重新输入坐标n);else if(x1|yN|yN)printf(操作错误,找不到相应坐标n);continue;else if(op=.)if(mapxy=-1)printf(你踩到地雷了 嘿嘿 正确的地雷位置是这样的n);out_map();break;else if(mapxy=0&user_mapxy=0)search(x,y);else user_mapxy=1;else if(op=!)if(user_mapxy=1)printf(该位置已被标记,不能再标记 n);continue;user_mapxy=2;marknum+;else if(op=c&user_mapxy=2) /取消(x,y)的标记user_mapxy=0;marknum-;else printf(操作错误 该操作无意义 n); continue;out_user_map();if(k)printf(goo good!you get it 游戏成功结束n);break;if(marknumminenum)printf(还有%d颗地雷没有被标记 n,minenum-marknum);else if(marknum=minenum&!k)printf(%d颗地雷已经全部被标记,但部分标记错误,请重试下 !n,minenum);五:程序设计所有的准备工作都做好了,现在就来构造程序的框架吧,这是我们的大体思路: void random_map() . Void playgame() . .out_user_map();While(1) . . Search(); .out_user_map();主程序int main() .根据这个框架,我们很快就能把程序写出来。下面是完整的程序代码:#include#include#include#include#define N 10#define minenum 10/*在map中各字符或数字分别表示: -1:(x,y)位置上为地雷,显示时用*表示。 08:(x,y)位置上没有地雷,该数字为8个相邻位置上地雷的个数。 在umap中各字符或数字分别表示: 0:表示用户没有点开(x,y)位置; 1:表示用户已经点开(x,y)位置; 2:表示用户已经把(x,y)位置标记为地雷。 操作说明: .:表示点开; !:表示地雷; c:表示取消标记的地雷; q:表示退出游戏。*/int map100100=0;/初始化的地图int user_map100100=0; /显示给用户看的地图char line100; /用于地图图像化的输出int rightmarknum=0; /用户正确地标记出地雷的个数int marknum=0; /用户标记出地雷的个数int dir82=-1,-1,-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1;/方便计算每个位置相邻的8个位置用的。bool k=false; /在out_umap()函数中判断是否游戏结束;/输出用户地图:void out_user_map()rightmarknum=0;int i,j;for(i=1;i=N;i+)for(j=1;j=N;j+)if(user_mapij=2&mapij=-1)rightmarknum+;if(rightmarknum=minenum)/用于显示所有还未打开的地图k=true;for(i=1;i=N;i+)for(j=1;j=N;j+)if(user_mapij=0)user_mapij=1;/显示地图: line0=40; for(i=1;i=4*N-1;i+) linei=_; linei=0; puts(line); for(i=1;i=N;i+) line0=|; for(j=1;j=N;j+) line4*j-3=_; if(user_mapij=0)line4*j-2=_; else if (user_mapij=1)line4*j-2=48+mapij; else if (user_mapij=2)line4*j-2=!;line4*j-1=_; line4*j=|; line4*N+1=0; puts(line); /输出实际地图:void out_map()int i,j;line0=40; for(i=1;i=4*N-1;i+) linei=_; linei=0; puts(line); for(i=1;i=N;i+) line0=|; for(j=1;j=N;j+) line4*j-3=_; if(mapij=-1)line4*j-2=*; else line4*j-2=48+mapij;line4*j-1=_; line4*j=|; line4*N+1=0; puts(line); /随机生成地图void random_map()int i=1,j,k;srand(unsigned)time(0);int num1,num2;while(i=minenum)num1=1+(int)(1.0*N*rand()/(RAND_MAX+1);/产生1N之间的随机数;num2=1+(int)(1.0*N*rand()/(RAND_MAX+1);/产生1N之间的随机数;if(num1N|num2N|mapnum1num2=-1) /排除第0行和第0列,及重复的地雷位置continue;mapnum1num2=-1;i+;int mines; /对于其余位置统计其周围8个位置上地雷的个数for(i=1;i=N;i+)for(j=1;j=N;j+)if(mapij=-1)continue;mines=0;for(k=0;k8;k+)if(mapi+dirk0j+dirk1=-1)mines+;mapij=mines;/如果用户点开的位置上雷的个数为0,则程序自然点开一片连续的没有地雷的区域void search(int x,int y)user_mapxy=1; /标记点开(x,y)位置int dx,dy;for(int i=0;i8;i+) /是否点开周围的8个位置dx=x+diri0;dy=y+diri1;if(dxN|dyN)continue;else if(mapdxdy!=0)user_mapdxdy=1;else if(mapdxdy=0&user_mapdxdy=0) /如果(x,y)周围相邻位置没有地雷,且也没有被点开过,则沿着这些位置递归地点开search(dx,dy);/主程序void playgame()out_user_map();int x,y;char op;prin

温馨提示

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

评论

0/150

提交评论