C++实现简单的控制台版扫雷游戏教程

听雨眠
听雨眠
发布时间:2026-10-13| 5人浏览过
原创

这篇文章将详细介绍如何利用 C++ 面向对象的特性,从零构建一个简单的控制台扫雷程序。我们将通过类定义方块状态、处理键盘输入以及实现基本的胜利判定条件,来完整演示该小游戏的底层逻辑。

核心结果与目标

本项目的最终目标是运行一个可以在 Windows 控制台窗口中进行互动的扫雷程序。玩家通过键入行号和列号来翻开方块;如果翻到无雷的空白区域,程序会自动展开周围的相邻格子。成功翻开所有非雷方块即判定胜利。

准备条件与环境配置

在开始编写代码前,需要确认以下环境条件:

  • 编译器:支持 C++11 或更高标准(如 GCC, Clang 或 MSVC)。
  • 操作系统:由于使用了 Windows 特有的 API 控制光标位置,本项目主要在 Windows 环境下编译运行。如需跨平台,需替换光标定位部分。
  • 依赖库:<stdio.h> 用于输入输出,<Windows.h> 用于控制台颜色与光标控制。

真实操作顺序:开发步骤详解

第1步:设计网格数据结构与类定义

我们需要一种方式来存储每一个方块的状态。创建一个 Cube 类非常合适。

目的:封装每个格子的信息,包括是否包含地雷、是否已被打开、以及周围的地雷数量。

关键参数:

  • ifHaveBomb: 布尔值,标记地雷。
  • ifOpen: 布尔值,记录格子是否已被玩家翻开。
  • nearBombNumber: 整型,记录周围8个格子内地雷的数量。
class Cube {
private:
 bool ifHaveBomb;
 bool ifOpen;
 int nearBombNumber;
public:
 void setOpen() { ifOpen = true; }
 bool getOpen() { return ifOpen; }
 void setNearBombNumber(int number) { nearBombNumber = number; }
 void haveBomb() { ifHaveBomb = true; }
 bool getIfHaveBomb() { return ifHaveBomb; }
 int getNearBombNumber() { return nearBombNumber; }
 // 重置初始化
 void resetCube(bool ifhavebomb = false, bool ifopen = false, int nearbombnumber = 0){
  ifHaveBomb = ifhavebomb;
  ifOpen = ifopen;
  nearBombNumber = nearbombnumber;
 } 
};

第2步:初始化全局常量与二维数组

使用宏定义设置游戏难度。这里以 9x9 的网格为例。

入口:全局变量区

动作:

const int MAXX = 9;      // 宽
const int MAXY = 9;      // 高
const int BOMBNUMBER = 10; // 地雷总数

创建覆盖整个区域的二维对象数组:

Cube cube[MAXX][MAXY];

第3步:游戏启动与随机布雷逻辑

目的:确保每次游戏开始后,地雷的位置是随机分布的。

重要参数:srand() 种子函数。

在 gameStart 流程中:

  1. 调用 resetCube() 将所有格子清空。
  2. 使用 setBomb() 循环生成指定数量的地雷。利用 rand() 算法获取随机的 x,y 坐标,并检查该位置是否已有地雷。
  3. 对所有格子调用 checkAndSetNearBombNumber(),预先计算好每个非雷格子周围的雷数,以便后续展示数字。
void gameStart() {
 for (int i = 0; i < MAXY; i++) {
  for (int j = 0; j < MAXX; j++) {
   cube[j][i].resetCube();
  }
 }
 setBomb(BOMBNUMBER);
 for (int i = 0; i < MAXY; i++) {
  for (int j = 0; j < MAXX; j++) {
   checkAndSetNearBombNumber(j, i);
  }
 }
}

第4步:控制台渲染与坐标映射

为了让玩家在命令行中看到图形化的界面,需要使用 API 控制光标的移动。

入口:Show() 函数

操作:遍历整个数组,根据 getOpen() 的值决定显示“■”(未翻开)、数字或空格(已翻开),并在最后执行 system("cls") 刷新屏幕。

第5步:玩家输入与胜负交互判断

这是游戏的核心循环。

目的:接收用户输入并进行合法性校验。

  1. 读取输入的 x, y 坐标。
  2. 判断越界、重复点击或踩雷情况。
  3. 如果是安全的且周围雷数为 0,触发递归展开。
// 简化的输入交互逻辑
bool player() {
 int x, y;
 scanf("%d %d", &x, &y);
 // ... 边界检查及踩雷检测 ...
 cube[x][y].setOpen();
 if (cube[x][y].getNearBombNumber() == 0) {
  autoOpen(x, y); // 递归清空周边
 }
 show();
 return !ifWin() && life;
}

第6步:扩展空白区域的递归算法

描述:当玩家翻开一个周围没有地雷的格子时,按照扫雷规则,其上下左右及斜对角的所有安全格也应被一同翻开。

使用深度优先搜索(DFS)的思想,检查当前格子的 8 个邻居,如果邻居未被打开且也是空白的,则继续向更深层递归;如果邻居周围有雷,则翻开并停止对该分支的探索。

void autoOpen(int x, int y) {
 for (int i = -1; i <= 1; i++) {
  for (int j = -1; j <= 1; j++) {
   int nx = x + i, ny = y + j;
   // 边界检查与安全判断... 
   if (...) {
    if (grid[nx][ny].getNearBombNumber() == 0) {
     grid[nx][ny].setOpen();
     autoOpen(nx, ny);
    } else {
     grid[nx][ny].setOpen();
    }
   }
  }
 }
}

完成判断与排错说明

完成判断:当程序输出“祝贺你,你胜利了!”并且棋盘上所有的“■”都被揭开为数字或空格时,即代表通关。

潜在问题排查:

  • 无限递归/栈溢出:如果 autoOpen 逻辑中存在环状判断而未加入已访问状态的阻断,可能会导致崩溃。上述代码已通过 getOpen() 提前阻止了二次调用。
  • 中文乱码:在某些终端运行时,打印“×你踩中地雷了”可能出现乱码,建议保存源文件编码为 UTF-8 或在控制台设置GBK。
  • 光标闪烁/掉帧:频繁调用 system("cls") 会导致控制台闪屏。在实际生产中,通常使用双缓冲技术来解决此问题。

简要总结

本文介绍了如何应用 C++ 编写基础的扫雷控制台版本。从定义方块属性,到动态规划布雷策略,再到运用递归清理空白区域,这是一套经典的入门级游戏开发实践方案。以上就是C++实现简单的扫雷游戏(控制台版)的详细内容,更多关于C++小游戏开发的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。