ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

数组和函数实践:扫雷游戏

数组和函数实践:扫雷游戏 数组和函数实践扫雷游戏文章目录数组和函数实践扫雷游戏一.扫雷游戏分析和设计一扫雷游戏的功能说明二游戏的分析和设计1.数据结构的分析2.文件结构设计二.扫雷游戏的代码实现一游戏大致流程二game函数内容1.定义mine数组和show数组2.初始化棋盘3.打印棋盘4.布置雷5.排雷三完整代码一.扫雷游戏分析和设计一扫雷游戏的功能说明使用控制台实现经典的扫雷游戏游戏可以通过菜单实现继续玩或者退出游戏扫雷的棋盘默认是9*9的格子默认随机布置10个雷可以排查雷如果位置不是雷就显示周围有几个雷如果位置是雷就炸死游戏结束把除10个雷之外的所有非雷都找出来排雷成功游戏结束游戏界面二游戏的分析和设计1.数据结构的分析扫雷的过程中布置的雷和排查出的雷的信息都需要存储所以需要一定的数据结构来存储这些信息。因为需要在9*9的棋盘上布置雷的信息和排查雷首先想到的就是创建一个9*9的数组来存放信息。空棋盘某位置布置雷就存放1没有布置雷就存放0。排雷的假设假设排查(2,4)这个坐标时访问周围的一圈8个绿色位置统计周围雷的个数是1但是排查(8,5)这个坐标时访问周围的⼀圈8个绿色位置统计周围雷的个数时最下面的三个坐标就会越界为了防止越界在设计的时候给数组扩大一圈雷还是布置在中间的9*9的坐标上周围一圈不去布置雷这样就解决了越界的问题。所以将存放数据的数组创建成11*11是比较合适。周围加上一圈后的棋盘再继续分析在棋盘上布置了雷的信息1和非雷的信息0假设我们排查了某一个位置后这个坐标处不是雷这个坐标的周围有1个雷那我们需要将排查出的雷的数量信息记录存储并打印出来作为排雷的重要参考信息。这个雷的个数信息如果存放在布置雷的数组中雷的信息和雷的个数信息就可能或产生混淆和打印上的困难。解决方案专门给一个棋盘对应一个数组mine存放布置好的雷的信息再给另外一个棋盘对应另外一个数组show存放排查出的雷的信息。这样就互不干扰了把雷布置到mine数组在mine数组中排查雷排查出的数据存放在show数组并且打印show数组的信息给后期排查参考。同时为了保持神秘show数组开始时初始化为字符*为了保持两个数组的类型一致可以使用同一套函数处理mine数组最开始也初始化为字符0布置雷改成字符1。如下图mine数组布置雷后的状态 和 show数组输出初始化的状态对应的数组应该是charmine[11][11]{0};//⽤来存放布置好的雷的信息charshow[11][11]{0};//⽤来存放排查出的雷的个数信息2.文件结构设计上一篇函数里介绍了多文件的形式对函数的声明和定义这里实践一下设计三个文件test.c 写游戏的测试逻辑game.c 写游戏中函数的实现game.h 写游戏需要的数据类型和函数声明二.扫雷游戏的代码实现一游戏大致流程test.c:用do_while循环上来先打印菜单。选1进入游戏由后面要写的game函数实现选0while的判断表达式的值为0循环直接结束退出游戏。二game函数内容1.定义mine数组和show数组game.h中:test.c中:game.c中:在game.h头文件中用define定义常量ROW,COL实际棋盘行和列ROWS,COLS加上外围一圈后棋盘行和列方便test.c,game.c中多次调用也方便后续修改棋盘大小直接在define处修改大小不用一个一个去修改。直接在test.cgame.h中包含game.h头文件即可使用。为了更加方便把stdio.h也包含在game.h中这样包含game.h的同时也可以包含stdio.h。技巧多个.c文件公用的东西库函数自定义函数常量都放到一个头文件中定义和声明会方便清晰很多。2.初始化棋盘在test.c中的game函数里写调用的函数雏形://初始化棋盘InitBoard(mine,ROWS,COLS,0);InitBoard(show,ROWS,COLS,*);注初始化的棋盘是加了外围一圈后的棋盘所以传入行列为ROWSCOLS。在game.c中写函数定义://初始化棋盘voidInitBoard(charBoard[ROWS][COLS],intr,intc,charset){for(inti0;ir;i){for(intj0;jc;j){Board[i][j]set;}}}Board接收要初始化的数组。r,c接收要遍历的行数和列数。set接收要初始化的目标字符。通过遍历数组的行和列拿到每个元素并赋给它目标字符完成初始化。在game.h中声明函数voidInitBoard(charBoard[ROWS][COLS],intr,intc,charset);3.打印棋盘在test.c中的game函数里写调用函数雏形://打印棋盘DisplayBoard(show,ROW,COL);//DisplayBoard(mine, ROW, COL);注(1) 打印的棋盘是真实棋盘大小所以传入行列为ROWCOL。(2) 在正式玩游戏时只显示show棋盘。显示mine棋盘是为了后面调试检查代码。在game.c中写函数定义://打印棋盘voidDisplayBoard(charBoard[ROWS][COLS],intr,intc){printf(------扫雷游戏------\n);inti0,j0;for(j0;jc;j)//打印列号{printf(%d ,j);}printf(\n);//打印完列号换行for(i1;ir;i){printf(%d ,i);//打印行号for(j1;jc;j){printf(%c ,Board[i][j]);}printf(\n);//打印完一行换行}printf(\n);//整体打完再换行}Board接收要打印的数组。r,c接收要遍历的行数和列数。通过遍历数组的行和列拿到每个元素并打印。同时要注意打印行号和列号方便玩游戏时快速找到某位置的行号和列号。在game.h中声明函数voidDisplayBoard(charBoard[ROWS][COLS],intr,intc);打印棋盘效果展示4.布置雷在test.c中的game函数里写调用函数雏形://布置雷SetBoard(mine,ROW,COL);DisplayBoard(mine,ROW,COL);//布雷成功后打印出来检查注是在真实棋盘上布置雷所以传入行列为ROWCOL。在main函数里生成随机的种子srand((unsignedint)time(NULL));注1初始化随机数生成器在整个工程里只用调用一次所以必须写到main函数里。2记得在game.h里包含头文件stdlib.h和time.h。在game.c中写函数定义://布置雷voidSetBoard(charBoard[ROWS][COLS],intr,intc){intcountEASY_COUNT;while(count){intxrand()%r1;//x的范围1~rintyrand()%c1;//y的范围1~cif(Board[x][y]0)//防止重复布雷{Board[x][y]1;count--;//每成功布置一个雷循环-1}}}Board接收要布雷的数组。r,c接收真实棋盘的行数和列数。在game.h中定义布雷常量EASY_COUNT方便随时修改。用真实棋盘的行数和列数rc限制随机坐标xy的范围把随即坐标对应的数组元素赋为1就成功布置了一个雷。在game.h中声明函数和布雷个数#defineEASY_COUNT10voidSetBoard(charBoard[ROWS][COLS],intr,intc);布雷效果展示5.排雷在test.c中的game函数里写调用函数雏形://排雷FindBoard(mine,show,ROW,COL);在game.c中写函数定义:辅助函数获得排查位置周围雷的个数size_tGetMineCount(charmine[ROWS][COLS],intx,inty)//返回雷的个数一定是正数所以用无符号整数{return(mine[x-1][y-1]mine[x-1][y]mine[x-1][y1]mine[x][y-1]mine[x][y1]mine[x1][y-1]mine[x1][y]mine[x1][y1])-8*0;//转换为对应的数字}计算某位置雷的个数原理数字字符 -0该数字字符对应的数字数字 0该数字对应的数字字符把排查位置的周围的8个数字字符转换为数字再相加得该位置周围雷的个数。待排查坐标xy周围8个字符的坐标如下图//排雷voidFindBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intr,intc){intx0,y0;intwin0;//成功排雷的个数while(winr*c-EASY_COUNT){printf(请输入要排查的坐标\n);scanf(%d%d,x,y);if((x1xr)(y1yc)){if(show[x][y]*){if(mine[x][y]!1){size_tcountGetMineCount(mine,x,y);show[x][y]count0;//转换为对应的字符DisplayBoard(show,ROW,COL);win;}else{printf(很遗憾你被炸死了\n);DisplayBoard(mine,ROW,COL);//为了让玩家死得瞑目打印minebreak;//跳出循环}}else{printf(该坐标已排查过请重新输入\n);}}else{printf(输入的坐标非法请重新输入\n);}}//来到这里有两种情况1.炸死了游戏结束。2.排雷成功if(winr*c-EASY_COUNT){printf(恭喜你排雷成功\n);DisplayBoard(mine,ROW,COL);}}mine:接收mine数组用于排查某位置雷的个数游戏最终显示。show:接受show数组,用于游戏中的显示。rc:接收真实棋盘的行列。把除雷以外剩余的位置作循环次数每成功排完一个雷循环次数减一。在game.h中声明函数voidFindBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intr,intc);效果展示检查排雷不成功的情况检查排雷成功的情况为方便把EASY_COUNT设为80即只有一个位置不是雷并打印出mine棋盘来作弊以便快速检查。三完整代码game.h:#includestdio.h#includestdlib.h#includetime.h#defineROW9#defineCOL9#defineROWSROW2#defineCOLSCOL2#defineEASY_COUNT80voidInitBoard(charBoard[ROWS][COLS],intr,intc,charset);voidDisplayBoard(charBoard[ROWS][COLS],intr,intc);voidSetBoard(charBoard[ROWS][COLS],intr,intc);voidFindBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intr,intc);game.c:#includegame.h//初始化棋盘voidInitBoard(charBoard[ROWS][COLS],intr,intc,charset){for(inti0;ir;i){for(intj0;jc;j){Board[i][j]set;}}}//打印棋盘voidDisplayBoard(charBoard[ROWS][COLS],intr,intc){printf(------扫雷游戏------\n);inti0,j0;for(j0;jc;j)//打印列号{printf(%d ,j);}printf(\n);//打印完列号换行for(i1;ir;i){printf(%d ,i);//打印行号for(j1;jc;j){printf(%c ,Board[i][j]);}printf(\n);//打印完一行换行}printf(\n);//整体打完再换行}//布置雷voidSetBoard(charBoard[ROWS][COLS],intr,intc){intcountEASY_COUNT;while(count){intxrand()%r1;//x的范围1~rintyrand()%c1;//y的范围1~cif(Board[x][y]0)//防止重复布雷{Board[x][y]1;count--;//每成功布置一个雷循环-1}}}size_tGetMineCount(charmine[ROWS][COLS],intx,inty)//返回雷的个数一定是正数所以用无符号整数{return(mine[x-1][y-1]mine[x-1][y]mine[x-1][y1]mine[x][y-1]mine[x][y1]mine[x1][y-1]mine[x1][y]mine[x1][y1])-8*0;//转换为对应的数字}//排雷voidFindBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intr,intc){intx0,y0;intwin0;//成功排雷的个数while(winr*c-EASY_COUNT){printf(请输入要排查的坐标\n);scanf(%d%d,x,y);if((x1xr)(y1yc)){if(show[x][y]*){if(mine[x][y]!1){size_tcountGetMineCount(mine,x,y);show[x][y]count0;//转换为对应的字符DisplayBoard(show,ROW,COL);win;}else{printf(很遗憾你被炸死了\n);DisplayBoard(mine,ROW,COL);//为了让玩家死得瞑目打印minebreak;//跳出循环}}else{printf(该坐标已排查过请重新输入\n);}}else{printf(输入的坐标非法请重新输入\n);}}//来到这里有两种情况1.炸死了游戏结束。2.排雷成功if(winr*c-EASY_COUNT){printf(恭喜你排雷成功\n);DisplayBoard(mine,ROW,COL);}}test.c:#includegame.hvoidmenu(){printf(-----------------------------------\n);printf(----------- 1.play ---------\n);printf(----------- 2.exit ---------\n);printf(-----------------------------------\n);}voidgame(){//定义两个棋盘数组charmine[ROWS][COLS];//存放雷的信息charshow[ROWS][COLS];//存放排查雷的信息//初始化棋盘InitBoard(mine,ROWS,COLS,0);InitBoard(show,ROWS,COLS,*);//打印棋盘DisplayBoard(show,ROW,COL);//DisplayBoard(mine, ROW, COL);//布置雷SetBoard(mine,ROW,COL);DisplayBoard(mine,ROW,COL);//排雷FindBoard(mine,show,ROW,COL);}intmain(){srand((unsignedint)time(NULL));intinput0;do{menu();printf(请选择\n);scanf(%d,input);switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入错误请重新输入\n);break;}}while(input);return0;}
返回列表