[C语言初阶]扫雷小游戏
目录
- 一、原理及问题分析
- 二、代码实现
- 2.1 分文件结构设计
- 2.2 棋盘初始化与打印
- 2.3 布置雷与排查雷
- 2.4 游戏主流程实现
- 三、后期优化方向
在上一篇文章中,我们实现了我们的第二个游戏——三子棋小游戏。这次我们继续结合我们之前所学的所有内容,制作出我们的第三个项目——扫雷小游戏。
一、原理及问题分析
说起扫雷,这是一个非常经典的小游戏。扫雷游戏的核心逻辑是通过玩家输入的坐标排查雷的位置,若踩雷则游戏结束,否则显示周围雷的数量。接下来我们先以结构化的方式来宏观分析整个扫雷游戏中的关键要点:
-
双棋盘设计
- mine数组:存储雷的位置(1为雷,0为非雷)。
- show数组:存储玩家可见的信息(初始为*,排查后显示周围雷数,因为是字符,所以两个数组都是char类型)。
- 设计意义:若只创建一个数组,雷为1,不是雷为0,若这个坐标周围只有1个雷,则分不清是雷,还是排查出的雷的信息,有歧义,所以再创建一个额外数组,专门用来存放排查出的雷的信息,只打印这个数组即可,用%c打印。
-
边界处理
- 实际使用11x11的数组(通过ROWS和COLS定义),但只操作中间的9x9区域(通过ROW和COL定义)。
- 目的:排查雷时边界容易越界,所以要实现9x9棋盘实际是创建11x11的数组才不会越界,。 但不要直接写数字,而是定义行和列的符号,方便后期修改。
-
模块化设计
- test.c:处理菜单、循环流程和用户输入。
- game.c:实现游戏核心逻辑(初始化、布置雷、排查雷)。
- game.h:声明函数和定义常量。
-
游戏流程(在三子棋和之前的猜数字小游戏中已实现过)
- 使用do-while循环支持重复游玩。
- 玩家输入坐标后,通过递归展开无雷区域(进阶功能需自行实现)。
二、代码实现
2.1 分文件结构设计
文件分工与核心函数:
- game.h:定义常量、声明函数。
// game.h #pragma once #include #include #include // 常量定义:实际操作的棋盘大小为9x9,扩展为11x11避免越界 #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY 10 // 默认雷的数量 // 函数声明 void Start(char arr[ROWS][COLS], int rows, int cols, char get); // 初始化棋盘 void Display(char arr[ROWS][COLS], int row, int col); // 打印棋盘 void Set(char arr[ROWS][COLS], int row, int col); // 布置雷 int Choose(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); // 排雷逻辑
- test.c:主流程和菜单逻辑。
- game.c:核心功能实现。
2.2 棋盘初始化与打印
1. 初始化函数 Start
- 功能:将棋盘所有位置初始化为指定字符(mine初始为'0',show初始为'*')因为一个函数要实现两种不同内容初始化,所以多加一个参数。
// game.c void Start(char arr[ROWS][COLS], int rows, int cols, char get) { for (int i = 0; i
2. 打印函数 Display
- 功能:打印棋盘,为了美化棋盘显示,优化玩家体验,我们添加了行列号和分隔线。
// game.c void Display(char arr[ROWS][COLS], int row, int col) { printf("--------扫雷游戏--------\n"); // 打印列号(顶部标签) printf(" "); // 对齐行号 for (int i = 1; i printf("%d ", i); } printf("\n"); // 打印分隔线 printf(" "); for (int i = 1; i printf("--"); } printf("\n"); // 打印棋盘内容(带行号) for (int i = 1; i printf("%d |", i); // 行号+左侧竖线 for (int j = 1; j printf("%c ", arr[i][j]); // 打印棋盘元素 } printf("\n"); } printf("--------扫雷游戏--------\n"); } int count = EASY; // 雷的数量 while (count) { int x = rand() % row + 1; // 生成1~9的随机坐标 int y = rand() % col + 1; if (arr[x][y] == '0') { // 仅当该位置无雷时布置 arr[x][y] = '1'; // 标记为雷 count--; } } } // 周围8个坐标的字符值相加('0'或'1'),再减去8*'0'得到实际数字 return arr[x-1][y-1] + arr[x-1][y] + arr[x-1][y+1] + arr[x][y-1] + arr[x][y+1] + arr[x+1][y-1] + arr[x+1][y] + arr[x+1][y+1] - 8 * '0'; } int x = 0, y = 0; int Win = 0; // 记录已排查的非雷区域数量 while (Win
三、后期优化方向
- 递归展开:若排查坐标周围无雷(即雷数为0),自动展开相邻区域。
- 标记雷:允许玩家输入特殊指令(如m 3 4)标记可能为雷的位置。
- 难度调整:通过修改EASY的值实现不同难度的雷数设置。
- 界面优化:使用Windows API或第三方库(如EasyX)添加图形界面。
简单地总结一下,在这篇文章中,我们通过分文件设计和模块化的运用,将扫雷游戏的逻辑逐一地理清并且给出了后期扩展的方向。我们在代码中通过定义符号常量(如ROW、EASY)提高可维护性,方便后期修改,这是一种很重要的编程习惯。我们通过我们现阶段所学的知识,做出了这个经典的游戏,这是对我们所学知识的肯定,也是我们对经典跨越时间的致敬。最后,我想送给大家一句话:"人生没有白走的路,每一步都算数。"我们的决定,决定了我们。在介绍完了两个C语言的项目之后,下一章,我们将回归C语言的知识学习,介绍一下操作符的相关知识,敬请期待。
作者其他文章链接:
[C语言初阶]三子棋小游戏
[C语言初阶]数组
[C语言初阶]递归
Gitee详细使用教程
- 功能:打印棋盘,为了美化棋盘显示,优化玩家体验,我们添加了行列号和分隔线。
- 功能:将棋盘所有位置初始化为指定字符(mine初始为'0',show初始为'*')因为一个函数要实现两种不同内容初始化,所以多加一个参数。
-
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。