C语言二维数组实战:实现扫雷游戏

Luna
Luna
发布时间:2026-10-15| 5人浏览过
原创

本文详细介绍如何利用C语言的二维数组在控制台中开发一款扫雷游戏。通过分析棋盘数据的存储结构、防越界处理技巧以及随机布雷算法,完整呈现从菜单设计到游戏核心逻辑的代码实现过程,适合初学者深入理解数组操作。

结果或目标

使用C语言编写一个基于控制台的扫雷程序。程序需具备以下功能: - 显示 9×9 的游戏界面,初始状态隐藏所有格子。 - 系统随机生成 10 个地雷位置。 - 用户输入坐标后,若未踩雷则显示该位置周围 8 个方向的雷数;若踩雷则游戏结束并展示全盘。 - 在未踩雷的情况下翻开所有非雷格子即视为胜利。

准备条件

为了实现该功能,需要构建三个核心文件: - game.h:包含宏定义(行列数、雷数)、函数声明及必要的头文件引入。 - test.c:负责主循环、菜单打印及游戏流程调度。 - game.c:实现棋盘初始化、展示、布雷及找雷的核心逻辑。

第1步:定义数据结构与接口

目的:确立棋盘大小及安全边界的数学模型,提供标准化的函数接口。 操作:
在 game.h 中,由于需要统计边缘位置的周围雷数,直接访问相邻索引会导致数组越界。因此,实际使用的逻辑数组大小应为 ROWS x COLS(例如 11x11),而显示给用户的仅为中间部分(9x9)。

#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#define ROW 9          // 显示行数
#define COL 9          // 显示列数
#define ROWS (ROW+2)   // 实际行数,含安全边
#define COLS (COL+2)   // 实际列数,含安全边
#define MINE_NUM 10    // 雷的数量

#include <stdlib.h>
#include <time.h>

// 函数原型声明
void InitBoard(char board[][COLS], int rows, int cols, char set);
void DisplayBoard(char board[][COLS], int row, int col);
void SetMine(char board[][COLS], int row, int col);
void FindMine(char mine[][COLS], char show[][COLS], int row, int col);
#endif

第2步:实现主控流程

目的:建立游戏入口,处理用户选择并调用游戏模块。 操作:
在 test.c 中,main 函数通过 do-while 循环维持程序运行。进入 game() 后,分配两个二维数组: - Mine[ROWS][COLS]:后台数据,'0'表示无雷,'1'表示有雷。 - Show[ROWS][COLS]:前台数据,初始化全部为 '*' 以遮蔽信息。

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void menu()
{
    printf("********0.exit********\n");
    printf("********1.play********\n");
    printf("**********************\n");
}

void game()
{
    char mine[ROWS][COLS] = { 0 };
    char show[ROWS][COLS] = { 0 };

    // 1. 初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');

    // 2. 布置地雷
    SetMine(mine, ROW, COL);

    // 3. 开始游戏
    FindMine(mine, show, ROW, COL);
}

int main()
{
    int input = 0;
    do {
        menu();
        printf("请选择:>>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入无效,请重新输入\n");
        }
    } while (input); // 输入为0时退出循环
    return 0;
}

第3步:实现底层逻辑函数

目的:完成数据初始化、渲染、随机算法及核心判定逻辑。
操作:
在 game.c 中:

  • 初始化:使用嵌套循环遍历数组赋予指定字符。
  • 打印:DisplayBoard 仅输出 1 到 ROW 的范围,跳过第 0 行/列和最后新增的一行/列,保持界面整洁。
  • 布雷:利用 srand(time(NULL)) 配合 rand() % ROW + 1 在有效范围内(避开边缘安全层)随机放置‘1’。
  • 计算雷数:针对用户输入的坐标 (x, y),累加其周围 8 个邻接点的值。注意这里字符 '1' 的 ASCII 码为 49,减去 8 个 '0' (ASCII 48) 即可得到整数雷数。
  • 交互循环:检查输入合法性,若无雷则更新显示矩阵并减少剩余空格计数;若遇雷则调用 DisplayBoard(mine) 揭示真相。

第4步:关键排错与注意事项

问题1:数组越界风险
当用户输入边界坐标(如 1,1)时,程序需读取 (0,0) 到 (2,2) 的区域。若数组不扩充,索引 -1 将导致非法内存访问。解决方案是在物理内存中开辟多出一圈的“安全垫”,且将该圈初始化为 '0'。

问题2:字符与整数的转换
数组元素类型为 char,但统计雷数时需进行数学加法。示例代码中的写法 Mine[x-1][y-1] + ... - 8*'0' 是一种紧凑实现。需注意,如果某位置没有地雷是字符 '0',它参与加法会产生偏移量,必须统一减去基准值 '0' 才能还原为数值 0 或 1。

问题3:随机数重复
虽然简单的 rand() 可能产生重复坐标,但在本实现的简单版本中,重复覆盖只是导致该位置保持为 '1'。若要求严格保证 N 个雷且不重叠,需加入判断逻辑确保写入前该坐标未被占用。

简要总结

通过本案例,我们掌握了如何利用 C 语言二维数组处理带有“上下文依赖”的逻辑问题。特别是通过扩充数组维度来解决边界检测难题,以及灵活运用字符 ASCII 码进行轻量级数据存储的技巧。以上就是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 算法库。