当前位置: 首页 > news >正文

[C语言初阶]扫雷小游戏

目录

  • 一、原理及问题分析
  • 二、代码实现
    • 2.1 分文件结构设计
    • 2.2 棋盘初始化与打印
    • 2.3 布置雷与排查雷
    • 2.4 游戏主流程实现
  • 三、后期优化方向

在上一篇文章中,我们实现了我们的第二个游戏——三子棋小游戏。这次我们继续结合我们之前所学的所有内容,制作出我们的第三个项目——扫雷小游戏。
在这里插入图片描述

一、原理及问题分析

说起扫雷,这是一个非常经典的小游戏。扫雷游戏的核心逻辑是通过玩家输入的坐标排查雷的位置,若踩雷则游戏结束,否则显示周围雷的数量。接下来我们先以结构化的方式来宏观分析整个扫雷游戏中的关键要点:

  1. 双棋盘设计

    • mine数组:存储雷的位置(1为雷,0为非雷)。
    • show数组:存储玩家可见的信息(初始为*,排查后显示周围雷数,因为是字符,所以两个数组都是char类型)。
    • 设计意义:若只创建一个数组,雷为1,不是雷为0,若这个坐标周围只有1个雷,则分不清是雷,还是排查出的雷的信息,有歧义,所以再创建一个额外数组,专门用来存放排查出的雷的信息,只打印这个数组即可,用%c打印。
  2. 边界处理

    • 实际使用11x11的数组(通过ROWSCOLS定义),但只操作中间的9x9区域(通过ROWCOL定义)。
    • 目的:排查雷时边界容易越界,所以要实现9x9棋盘实际是创建11x11的数组才不会越界,。 但不要直接写数字,而是定义行和列的符号,方便后期修改。
  3. 模块化设计

    • test.c:处理菜单、循环流程和用户输入。
    • game.c:实现游戏核心逻辑(初始化、布置雷、排查雷)。
    • game.h:声明函数和定义常量。
  4. 游戏流程(在三子棋和之前的猜数字小游戏中已实现过)

    • 使用do-while循环支持重复游玩。
    • 玩家输入坐标后,通过递归展开无雷区域(进阶功能需自行实现)。

二、代码实现

2.1 分文件结构设计

文件分工与核心函数

  • game.h:定义常量、声明函数。
// game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>// 常量定义:实际操作的棋盘大小为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 < rows; i++) {for (int j = 0; j < cols; j++) {arr[i][j] = get; // 将每个元素设置为传入的字符('0'或'*')}}
}

2. 打印函数 Display

  • 功能:打印棋盘,为了美化棋盘显示,优化玩家体验,我们添加了行列号和分隔线。
// game.c
void Display(char arr[ROWS][COLS], int row, int col){printf("--------扫雷游戏--------\n");// 打印列号(顶部标签)printf("   "); // 对齐行号for (int i = 1; i <= col; i++){printf("%d ", i);}printf("\n");// 打印分隔线printf("   ");for (int i = 1; i <= col; i++) {printf("--");}printf("\n");// 打印棋盘内容(带行号)for (int i = 1; i <= row; i++) {printf("%d |", i); // 行号+左侧竖线for (int j = 1; j <= col; j++) {printf("%c ", arr[i][j]); // 打印棋盘元素}printf("\n");}printf("--------扫雷游戏--------\n");
}

运行效果

--------扫雷游戏--------1 2 3 4 5 6 7 8 9 -------------------
1 |* * * * * * * * * 
2 |* * * * * * * * * 
...(略)

2.3 布置雷与排查雷

1. 布置雷函数 Set

  • 功能:在9x9区域内随机生成雷。(关于rand函数的用法以及取余的技巧在之前的三子棋和猜数字小游戏中已经详细介绍过,这里不再赘述)
// game.c
void Set(char arr[ROWS][COLS], int row, int col){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--;}}
}

2. 计算周围雷数 get_mine

  • 功能:计算坐标(x,y)周围8个位置的雷数总和。 这个函数可以不用在game.h中声明,因为只是为了在排查雷的函数中临时用的,不会用在其他地方。
// game.c
int get_mine(char arr[ROWS][COLS], int x, int y) 
{// 周围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';
}

3. 排雷逻辑 Choose

  • 功能:处理玩家输入的坐标,判断是否踩雷或显示周围雷数。
// game.c
int Choose(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){int x = 0, y = 0;int Win = 0; // 记录已排查的非雷区域数量while (Win < ROW * COL - EASY) // 胜利条件:所有非雷区域均被排查{ printf("请选择排雷坐标(如2 3表示第二行第三列):>");scanf("%d %d", &x, &y);if (x >= 1 && y >= 1 && x <= row && y <= col)// 坐标合法性检查{ if (mine[x][y] == '1') // 踩雷{ printf("很遗憾,你被炸死了!\n");Display(mine, ROW, COL); // 展示雷的位置break; // 游戏结束} else  // 安全坐标{ int count = get_mine(mine, x, y); // 计算周围雷数show[x][y] = count + '0'; // 转换为字符存储(例如3 -> '3')Display(show, ROW, COL);Win++;}} else {printf("坐标非法!\n");}}if (Win == ROW * COL - EASY) // 胜利条件达成{ printf("恭喜通关!\n");Display(mine, ROW, COL); // 展示雷的位置}
}

2.4 游戏主流程实现

test.c:菜单和主循环逻辑。

// test.c
#include "game.h"void menu() {printf("*********************************\n");printf("*********************************\n");printf("***********扫雷小游戏************\n");printf("*********************************\n");printf("***********1.开始游戏************\n");printf("***********0.退出游戏************\n");printf("*********************************\n");printf("**********版本:Beta1.0***********\n");printf("**********作者:Yang210***********\n");printf("*********************************\n");printf("*********************************\n");printf("*********************************\n");
}void game() {char mine[ROWS][COLS]; // 存储雷的棋盘char show[ROWS][COLS]; // 显示给玩家的棋盘Start(mine, ROWS, COLS, '0'); // 初始化雷棋盘为全'0'Start(show, ROWS, COLS, '*'); // 初始化显示棋盘为全'*'Set(mine, ROW, COL);          // 布置雷Display(show, ROW, COL);      // 打印初始棋盘Choose(mine, show, ROW, COL); // 进入排雷逻辑
}int main() {srand((unsigned int)time(NULL)); // 设置随机数种子int input = 0;int add = 0; // 记录游戏次数do {menu();if (add == 0) {printf("请选择(输入1开始游戏,输入0退出游戏):>");} else {printf("是否继续游玩(输入1继续游玩,输入0退出游戏):>");}scanf("%d", &input);switch (input) {case 1:game();add++;break;case 0:printf("已退出游戏\n");break;default:printf("输入错误!\n");}} while (input); // input为0时退出循环return 0;
}

三、后期优化方向

  1. 递归展开:若排查坐标周围无雷(即雷数为0),自动展开相邻区域。
  2. 标记雷:允许玩家输入特殊指令(如m 3 4)标记可能为雷的位置。
  3. 难度调整:通过修改EASY的值实现不同难度的雷数设置。
  4. 界面优化:使用Windows API或第三方库(如EasyX)添加图形界面。

简单地总结一下,在这篇文章中,我们通过分文件设计和模块化的运用,将扫雷游戏的逻辑逐一地理清并且给出了后期扩展的方向。我们在代码中通过定义符号常量(如ROWEASY)提高可维护性,方便后期修改,这是一种很重要的编程习惯。我们通过我们现阶段所学的知识,做出了这个经典的游戏,这是对我们所学知识的肯定,也是我们对经典跨越时间的致敬。最后,我想送给大家一句话:"人生没有白走的路,每一步都算数。"我们的决定,决定了我们。在介绍完了两个C语言的项目之后,下一章,我们将回归C语言的知识学习,介绍一下操作符的相关知识,敬请期待。
请添加图片描述

作者其他文章链接:
[C语言初阶]三子棋小游戏
[C语言初阶]数组
[C语言初阶]递归
Gitee详细使用教程

相关文章:

  • Java 函数式接口(Functional Interface)
  • 符合Python风格的对象(使用 __slots__ 类属性节省空间)
  • DeepSeek 赋能数字农业:从智慧种植到产业升级的全链条革新
  • Windows 中动态库.dll 的 .lib 文件有什么作用?
  • SOC-ESP32S3部分:10-GPIO中断按键中断实现
  • 什么是模板字符串?比普通字符串的好处
  • mongodb语法$vlookup性能分析
  • YOLO11解决方案之使用 Streamlit 应用程序进行实时推理
  • github公开项目爬取
  • 【博客系统】博客系统第五弹:基于令牌技术实现用户登录接口
  • 【C++/控制台】迷宫游戏
  • SQL每日一练
  • CloudWeGo-Netpoll:高性能NIO网络库浅析
  • python web 开发-Flask-Login使用详解
  • AtCoder AT_abc407_c [ABC407C] Security 2
  • 开发者工具箱-鸿蒙设备信息功能开发实践
  • 神经算子与FNO技术详解
  • 浅析Spring AOP 代理的生成机制
  • 实现Web网站冷启动的全面指南
  • [软件测试_4] 沟通技巧 | 测试用例 | 设计方法
  • 做外贸去哪些网站找老外/网店运营培训
  • 织梦网站做关键词/学大教育一对一收费价格表
  • 建设网站对公司起什么作用/如何建立免费公司网站
  • 点图片跳到网站怎么做的/搜索软件
  • 网站负责人拍照/手机系统优化工具
  • 商品网站怎么做/百度推广需要多少钱