【学完 C 语言基础,用这个扫雷项目练手就够了】:数组和函数实践——扫雷游戏
文章目录前言1.扫雷游戏分析与设计1.1 扫雷游戏的功能说明1.2 游戏分析与设计1.2.1 数据结构的分析1.2.2 文件结构设计2.扫雷游戏代码实现2.1 详细讲解2.2 扫雷游戏的完整代码3. 扫雷游戏的扩展总结⽬录扫雷游戏分析和设计扫雷游戏的代码实现扫雷游戏的扩展前言扫雷作为一款伴随了几代人成长的经典益智小游戏以简单的规则、丰富的逻辑挑战成为了无数程序员入门编程世界时检验基础语法与算法能力的绝佳实战项目。对于 C 语言学习者而言从零实现一款控制台版扫雷游戏不仅能巩固二维数组操作、模块化编程、递归遍历、边界处理等核心知识点更能锻炼从需求分析到系统设计再到代码实现的完整工程化思维。本文将以扫雷游戏为载体从功能需求拆解、数据结构设计、文件结构规划到核心代码逐模块实现完整记录一个 C 语言控制台扫雷游戏的开发过程。无论你是刚学完数组与函数的 C 语言新手还是想通过经典项目回顾编程基础的开发者都能通过本文清晰的步骤讲解掌握扫雷游戏的实现原理并动手写出可运行的完整代码。同时文章最后也会分享扫雷游戏的拓展方向帮助大家在基础版本之上实现更多进阶功能1.扫雷游戏分析与设计扫雷游戏网页版 在线扫雷游戏1.1 扫雷游戏的功能说明• 使⽤控制台实现经典的扫雷游戏• 游戏可以通过菜单实现继续玩或者退出游戏• 扫雷的棋盘是9*9的格⼦• 默认随机布置10个雷• 可以排查雷◦ 如果位置不是雷就显示周围有几个雷◦ 如果位置是雷就炸死游戏结束◦ 把除10个雷之外的所有非雷都找出来排雷成功游戏结束初始界面雷的位置扫雷失败界面1.2 游戏分析与设计1.2.1 数据结构的分析扫雷的过程中布置的雷和排查出的雷的信息都需要存储所以我们需要⼀定的数据结构来存储这些信息。因为我们需要在9 * 9的棋盘上布置雷的信息和排查雷我们⾸先想到的就是创建⼀个9*9的数组来存放信息。那如果这个位置布置雷我们就存放1没有布置雷就存放0假设我们排查(2,5)这个坐标时我们访问周围的⼀圈8个⻩⾊位置统计周围雷的个数是1假设我们排查(8,6)这个坐标时我们访问周围的⼀圈8个⻩⾊位置统计周围雷的个数时最下⾯的三个坐标就会越界为了防⽌越界我们在设计的时候给数组扩⼤⼀圈雷还是布置在中间的9 * 9的坐标上周围⼀圈不去布置雷就⾏这样就解决了越界的问题。所以我们将存放数据的数组创建成11 * 11是⽐较合适。再继续分析我们在棋盘上布置了雷棋盘上雷的信息1和⾮雷的信息0假设我们排查了某⼀个位置后这个坐标处不是雷这个坐标的周围有1个雷那我们需要将排查出的雷的数量信息记录存储并打印出来作为排雷的重要参考信息的。那这个雷的个数信息存放在哪⾥呢如果存放在布置雷的数组中这样雷的信息和雷的个数信息就可能或产⽣混淆和打印上的困难。这⾥我们肯定有办法解决⽐如雷和⾮雷的信息不要使⽤数字使⽤某些字符就⾏这样就避免冲突了但是这样做棋盘上有雷和⾮雷的信息还有排查出的雷的个数信息就⽐较混杂不够⽅便。这⾥我们采⽤另外⼀种⽅案我们专⻔给⼀个棋盘对应⼀个数组mine存放布置好的雷的信息再给另外⼀个棋盘对应另外⼀个数组show存放排查出的雷的信息。这样就互不⼲扰了把雷布置到mine数组在mine数组中排查雷排查出的数据存放在show数组并且打印show数组的信息给后期排查参考。同时为了保持神秘show数组开始时初始化为字符 ‘*’为了保持两个数组的类型⼀致可以使⽤同⼀套函数处理mine数组最开始也初始化为字符’0’布置雷改成’1’。如下如对应的数组应该是1.2.2 文件结构设计之前学习了多⽂件的形式对函数的声明和定义这⾥我们实践⼀下我们设计三个⽂件2.扫雷游戏代码实现2.1 详细讲解1.首先我们应该先完成一个游戏界面菜单函数2.接下来要完成game()函数的具体实现将棋盘初始化并再写一个函数将两个棋盘打印出来初始化之后的棋盘接下来我们要在mine棋盘中放置雷这是放置雷的具体函数实现不知道rand()函数的请看 rand()函数介绍布置雷之后的棋盘展示接下来我们要做的就是排雷输入一个坐标检查起周围8个地方有没有雷有几个雷就在show[x][y]中展示出来比如我输入的坐标为【3 3】这个坐标不是雷并且它周围的8个位置不是雷说以这个坐标是展示出0因为这是我游戏内部的函数只用本游戏实现不想让其他人使用。static的介绍请看第六讲函数模块全知识点详解2.2 扫雷游戏的完整代码game.h#define_CRT_SECURE_NO_WARNINGS#includestdio.h#includestdlib.h#includetime.h#defineEASY_COUNT10#defineROW9#defineCOL9#defineROWSROW2#defineCOLSCOL2voidInitBoard(char[ROWS][COLS],intr,intc,charset);voidDisplayBoard(charboard[ROWS][COLS],intr,intc);voidSetMine(charboard[ROWS][COLS],intr,intc);//排查雷voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],intr,intc);test.c#define_CRT_SECURE_NO_WARNINGS#includegame.hvoidmenu(){printf(*******************************************\n);printf(**********玩游戏 请选择1****************\n);printf(**********退出游戏请选择0****************\n);printf(*******************************************\n);printf(*******************************************\n);}voidgame(){//printf(扫雷\n);charmine[ROWS][COLS];//存放的是雷的信息charshow[ROWS][COLS];//存放的是排查出的信息//初始化棋盘InitBoard(mine,ROWS,COLS,0);InitBoard(show,ROWS,COLS,*);//打印棋盘DisplayBoard(show,ROW,COL);DisplayBoard(mine,ROW,COL);//布置雷SetMine(mine,ROW,COL);DisplayBoard(mine,ROW,COL);//排雷FindMine(mine,show,ROW,COL);}intmain(){intinput0;srand((unsignedint)time(NULL));do{menu();printf(请选择);scanf(%d,input);switch(input){case1:printf(开始游戏 \n);game();break;case0:printf(退出游戏 \n);break;default:printf(选择错误请重新输入\n);break;}}while(input);return0;}game.c#define_CRT_SECURE_NO_WARNINGS#includegame.hvoidInitBoard(charboard[ROWS][COLS],intr,intc,charset){inti0;intj0;for(inti0;ir;i){for(intj0;jc;j){board[i][j]set;}}}voidDisplayBoard(charboard[ROWS][COLS],intr,intc){inti0;intj0;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);}voidSetMine(charboard[ROWS][COLS],intr,intc){//随机生成intcountEASY_COUNT;while(count){intxrand()%r1;intyrand()%c1;if(board[x][y]0)//这里你为啥加个分号呢小笨蛋{board[x][y]1;count--;}}}staticsize_tGetMineCount(charmine[ROWS][COLS],intx,inty){returnmine[x-1][y]mine[x-1][y-1]mine[x][y-1]mine[x1][y-1]mine[x1][y]mine[x1][y1]mine[x][y1]mine[x-1][y1]-8*0;}voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],intr,intc){intx0;inty0;intwin0;while(winr*c-EASY_COUNT){printf(请输入要排查的坐标\n);scanf(%d%d,x,y);if(x1y1xryc){if(show[x][y]*){if(mine[x][y]1){printf(很遗憾你被炸死了\n);DisplayBoard(mine,ROW,COL);break;}else//不是雷就要统计这个坐标点有几个雷周围有几个雷{size_tcountGetMineCount(mine,x,y);show[x][y](char)count0;DisplayBoard(show,ROW,COL);win;}}else{printf(该坐标已经被排查过了不用重复排查\n);}}else{printf(输入的坐标非法请重新输入\n);}}if(winr*c-EASY_COUNT){printf(恭喜你排雷成功\n);DisplayBoard(mine,ROW,COL);}}3. 扫雷游戏的扩展• 是否可以选择游戏难度简单 9 * 9棋盘10个雷中等16 * 16棋盘40个雷困难30 * 16棋盘99个雷• 如果排查位置不是雷周围也没有雷可以展开周围的一片• 是否可以标记雷• 是否可以加上排雷的时间显示下一讲我将实现这个游戏更加复杂的功能使我们的游戏更好玩本讲只是扫雷游戏最基本的功能后面我会陆续更新更多功能最后达到下面这个扫雷游戏的功能在线扫雷游戏扫雷游戏总结本文从需求分析、系统设计到代码实现完整介绍了一款 C 语言控制台版扫雷游戏的开发流程。通过分文件模块化的设计方式我们将游戏拆分为数据存储、逻辑处理、用户交互等多个模块实现了雷区生成、棋盘展示、坐标排查、递归展开、胜负判断等核心功能同时也覆盖了 C 语言二维数组、函数封装、多文件编程等关键知识点的实际应用。在整个开发过程中我们也深刻体会到了编程的工程化思维从前期的数据结构设计与文件结构规划到中期的逐模块功能实现与边界问题处理再到后期的代码优化与逻辑调试每一步都体现了 “先设计后实现” 的重要性。对于 C 语言初学者而言这个项目不仅能帮你巩固基础语法更能培养解决复杂问题的拆解能力。当然本文实现的仅为扫雷游戏的基础版本还有很多可以拓展的方向比如增加难度选择、计时功能、标记雷区、排行榜系统甚至是基于图形库实现可视化界面。希望本文的内容能为大家提供一个清晰的开发思路也欢迎大家在评论区交流拓展思路一起完善属于自己的扫雷游戏。