公司动态

【C语言】百行代码实现扫雷游戏

📅 2026/7/14 14:58:56
【C语言】百行代码实现扫雷游戏
文章目录一、设计思路1. 游戏规则2. 数据结构设计3. 边界处理二、代码解析1. 头文件game.h2.功能实现game.c2.1 初始化棋盘initboard2.2 打印棋盘display_board2.3 随机布置地雷set_mine2.4 计算周围地雷数get_mine_count2.5 玩家排查地雷find_mine3. 主流程控制(main.c)三、运行效果与优化方向1. 运行示例2. 可优化功能四、源码一、设计思路1. 游戏规则棋盘由N×N的格子组成随机隐藏一定数量的地雷玩家每次选择一个格子进行排查若格子是地雷游戏结束若格子不是地雷显示周围8个格子中地雷的数量若排查完所有非地雷格子游戏结束2. 数据结构设计实现扫雷的关键是双棋盘设计地雷棋盘mine存储地雷的真实位置1表示地雷0表示非地雷仅程序内部使用显示棋盘show展示给玩家的棋盘*表示未排查数字表示周围地雷数玩家可见3. 边界处理为了避免计算边缘格子周围地雷时出现数组越界我们将实际使用的数组尺寸设为(ROW2)×(COL2)比显示的9×9棋盘多一圈边界这样无论计算哪个有效格子的周围都不会越界。二、代码解析我们的代码分为3个文件game.h宏定义、函数声明、头文件包含game.c游戏核心功能实现main.c游戏流程控制菜单、游戏启动1. 头文件game.h首先定义游戏的基础参数和函数接口确保代码的可维护性#define_CRT_SECURE_NO_WARNINGS1#includestdio.h#includestdlib.h#includetime.h// 显示的棋盘尺寸9×9#defineROW9#defineCOL9// 实际数组尺寸11×11含边界#defineROWSROW2#defineCOLSCOL2// 简单难度的地雷数量#defineEASY_COUNT10// 函数声明voidinitboard(charboard[ROWS][COLS],introws,intcols,charset);// 初始化棋盘voiddisplay_board(charboard[ROWS][COLS],introw,intcol);// 打印棋盘voidset_mine(charboard[ROWS][COLS],introw,intcol);// 布置地雷intget_mine_count(charmine[ROWS][COLS],intx,inty);// 计算周围地雷数voidfind_mine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol);// 排查地雷2.功能实现game.c2.1 初始化棋盘initboard初始化函数用于将两个棋盘设置为初始状态地雷棋盘mine初始化为0默认无地雷显示棋盘show初始化为*默认未排查voidinitboard(charboard[ROWS][COLS],introws,intcols,charset){for(inti0;irows;i){for(intj0;jcols;j){board[i][j]set;// 用指定字符填充整个数组包括边界}}}关键点通过传入set参数一个函数即可初始化两个棋盘。initboard(mine,ROWS,COLS,0);initboard(show,ROWS,COLS,*);2.2 打印棋盘display_board打印棋盘时需要兼顾美观和实用性我们会显示行列号方便玩家输入坐标voiddisplay_board(charboard[ROWS][COLS],introw,intcol){printf(-----扫雷游戏-----\n);// 打印列号0到 colfor(inti0;icol;i){printf(%d ,i);}printf(\n);// 打印每行数据带行号for(inti1;irow;i){printf(%d ,i);// 打印行号for(intj1;jcol;j){printf(%c ,board[i][j]);// 只打印有效区域1到row/col}printf(\n);}printf(\n);}2.3 随机布置地雷set_mine使用随机数生成器在mine棋盘上布置指定数量的地雷EASY_COUNT10确保不重复布置voidset_mine(charboard[ROWS][COLS],introw,intcol){intcountEASY_COUNT;while(count0){// 生成1到 row9的随机坐标intxrand()%row1;intyrand()%col1;// 若当前位置不是地雷布置地雷并减少计数if(board[x][y]0){board[x][y]1;// 1表示地雷count--;}}}注意随机数需要初始化种子在主函数中通过srand((unsigned int)time(NULL))实现确保每次运行地雷位置不同。2.4 计算周围地雷数get_mine_count当玩家排查到非地雷格子时需要计算其周围8个格子的地雷总数利用字符ASCII码特性简化计算intget_mine_count(charmine[ROWS][COLS],intx,inty){// 周围 8个格子的值相加1是490是48// 减去 8×048得到实际数字1或0的和returnmine[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的ASCII码是481是498个格子的字符值相加后减去8×48得到的就是周围地雷的数量例如3个地雷则总和为3×49 5×48 3×(481) 5×488×483减8×48后得3。2.5 玩家排查地雷find_mine核心游戏逻辑循环接收玩家输入的坐标判断是否踩雷更新显示棋盘直到胜利或失败voidfind_mine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol){intx,y;intwin0;// 已排查的非地雷格子数// 总非地雷格子数 9×9 - 10 71排查完则胜利while(winrow*col-EASY_COUNT){printf(输入要排查的坐标);scanf(%d %d,x,y);// 检查坐标合法性1到 9if(x1xrowy1ycol){if(mine[x][y]1){// 踩雷游戏结束printf(很遗憾被炸死\n);display_board(mine,row,col);// 显示所有地雷位置break;}else{// 未踩雷更新显示if(show[x][y]*){// 确保未重复排查intcountget_mine_count(mine,x,y);show[x][y]count0;// 相当于数字0的ASCII码.//例如count为1时148 --打印 49对应的字符也就是1display_board(show,row,col);win;// 增加已排查计数}else{printf(该坐标已排查过请重新输入\n);}}}else{printf(坐标无效1-%d, 1-%d请重新输入\n,row,col);}}// 若排查完所有非地雷格子胜利if(winrow*col-EASY_COUNT){printf(恭喜你排雷成功\n);display_board(mine,row,col);}}3. 主流程控制(main.c)整合上述功能实现游戏启动、菜单选择和流程控制voidmenu(){printf(********************************\n);printf(* 1.play *\n);printf(* 0.exit *\n);printf(********************************\n);}voidgame(){charmine[ROWS][COLS];// 地雷棋盘charshow[ROWS][COLS];// 显示棋盘// 初始化mine全为0非雷show全为*未排查initboard(mine,ROWS,COLS,0);initboard(show,ROWS,COLS,*);// 布置地雷set_mine(mine,ROW,COL);// 显示初始棋盘display_board(show,ROW,COL);// 开始排查find_mine(mine,show,ROW,COL);}voidtest(){intinput;srand((unsignedint)time(NULL));// 初始化随机数种子do{menu();printf(请选择);scanf(%d,input);switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入错误请重新选择\n);}}while(input!0);}intmain(){test();return0;}三、运行效果与优化方向1. 运行示例******************************** * 1.play * * 0.exit * ******************************** 请选择1 -----扫雷游戏----- 0 1 2 3 4 5 6 7 8 9 1 * * * * * * * * * 2 * * * * * * * * * ... 输入要排查的坐标3 4 -----扫雷游戏----- 0 1 2 3 4 5 6 7 8 9 1 * * * * * * * * * 2 * * * * * * * * * 3 * * * 1 * * * * * ...2. 可优化功能自动展开空白区域当周围地雷数为0时自动排查周围所有格子递归实现标记地雷功能允许玩家用P标记疑似地雷避免误触多难度选择增加中等15雷、困难20雷模式修改EASY_COUNT即可。四、源码game.h#define_CRT_SECURE_NO_WARNINGS1#includestdio.h#includestdlib.h#includetime.h#defineROW9#defineCOL9#defineROWSROW2#defineCOLSCOL2#defineEASY_COUNT10voidinitboard(charboard[ROWS][COLS],introws,intcols,charset);//初始化voiddisplay_board(charboard[ROWS][COLS],introw,intcol);//打印voidset_mine(charboard[ROWS][COLS],introw,intcol);//布置雷voidfind_mine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol);//排查雷game.c#define_CRT_SECURE_NO_WARNINGS1#includegame.hvoidinitboard(charboard[ROWS][COLS],introws,intcols,charset){for(inti0;irows;i){for(intj0;jcols;j)board[i][j]set;}}voiddisplay_board(charboard[ROWS][COLS],introw,intcol){printf(-----扫雷游戏-----\n);//先打印行列号for(inti0;icol;i)printf(%d ,i);printf(\n);//再打印棋盘数据for(inti1;irow;i){printf(%d ,i);for(intj1;jcol;j)printf(%c ,board[i][j]);printf(\n);}printf(\n);}voidset_mine(charboard[ROWS][COLS],introw,intcol){intcountEASY_COUNT;while(count){intxrand()%row1;//1-9intyrand()%col1;//1-9if(board[x][y]0)//不是雷{board[x][y]1;//布置雷count--;}}}intget_mine_count(charmine[ROWS][COLS],intx,inty){returnmine[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;}voidfind_mine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol){intx0;inty0;intwin0;while(winrow*col-EASY_COUNT){printf(输入要排查的坐标\n);scanf(%d %d,x,y);if(x1xrowy1ycol){if(mine[x][y]1){printf(很遗憾被炸死\n);display_board(mine,ROW,COL);break;}else{//这个坐标没有被排查过if(show[x][y]*){//统计雷个数intcountget_mine_count(mine,x,y);//存放到show中show[x][y]count0;display_board(show,ROW,COL);win;}elseprintf(该坐标已被排查过请重新排查\n);}}elseprintf(输出错误请重新输入);}if(wincol*row-EASY_COUNT){printf(恭喜你排雷成功\n);display_board(mine,ROW,COL);}}main.c#define_CRT_SECURE_NO_WARNINGS1#includegame.hvoidmenu(){printf(********************************\n);printf(* 1.play *\n);printf(* 0.exit *\n);printf(********************************\n);}voidgame(){charmine[ROWS][COLS];//布置雷的信息charshow[ROWS][COLS];//排除雷的信息initboard(mine,ROWS,COLS,0);//初始化initboard(show,ROWS,COLS,*);//初始化//display_board(mine, ROW, COL);//测试打印//display_board(show, ROW,COL);//测试打印set_mine(mine,ROW,COL);display_board(show,ROW,COL);//display_board(mine, ROW, COL);//测试布置雷是否成功find_mine(mine,show,ROW,COL);}voidtest(){intinput0;srand((unsignedint)time(NULL));//保证每次位置不同do{menu();printf(请输入);scanf(%d,input);switch(input){case1:game();break;case0:printf(退出游戏\n);break;default:printf(输入错误重新输入:\n);break;}}while(input);}intmain(){test();return0;}