C语言实现经典扫雷:核心逻辑与完整代码解析

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

本文详细解析使用C语言开发经典9x9扫雷游戏的实现原理。通过双二维数组设计(mine与show),结合边界扩展技巧解决坐标越界问题。文章涵盖棋盘初始化、布雷算法及排查雷核心逻辑,提供模块化头文件与源文件代码结构,帮助开发者掌握基础C语言在小型控制台游戏中的综合应用。

结果与目标

构建一个运行于控制台的经典扫雷游戏,初始界面为10个地雷散布的9x9网格。玩家输入行列坐标进行排查,系统反馈该位置周围的雷数;踩中地雷则游戏结束并展示全图,排尽所有非雷区域则判定胜利。

准备条件

  1. 开发环境:支持标准C语言编译的环境(如GCC、Clang或Visual Studio)。
  2. 关键数据结构:采用两个字符型二维数组。一个是真实布雷板 (Mine Board),用于存储雷的位置信息;另一个是显示面板 (Show Board),用于向玩家展示排查状态。
  3. 边界优化:虽然逻辑上是9x9网格,但为了简化计算并避免坐标越界检查,内部定义大小为(ROWS x COLS),其中 ROWS = ROW + 2,COLS = COL + 2。

真实操作顺序

第1步:模块划分与宏定义

首先建立工程的文件结构,通常分为头文件(声明接口与常量)、功能实现文件(函数逻辑)和测试主文件(主循环与菜单)。以下是头文件 game.h 的定义,它集中管理了棋盘尺寸与函数原型:

#define _CRT_SECURE_NO_WARNINGS
#define ROW 9
#define COL 9
#define ROWS (ROW + 2)
#define COLS (COL + 2)
#define EASY_COUNT 10
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

// 函数声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void SetMine(char mine[ROWS][COLS], int row, int col);
int GetMineCount(char mine[ROWS][COLS], int x, int y);
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

第2步:初始化棋盘

将两个棋盘分别填充不同的占位字符。Mine Board全部置为 '0'(表示无雷),Show Board全部置为 '*'(表示未排查)。注意传入的是扩大后的行列值。

// game.c
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = set;
        }
    }
}

第3步:布置地雷

利用随机数函数 rand() 生成棋盘内的横纵坐标。为了防止重复布雷,每次放置前需判断目标格子是否为 '0',若是则标记为 '1',直到布雷数量达到设定值。

void SetMine(char mine[ROWS][COLS], int row, int col)
{
    int count = EASY_COUNT;
    while (count)
    {
        int x = rand() % row + 1; // 确保范围在 1~row
        int y = rand() % col + 1; // 确保范围在 1~col
        if (mine[x][y] == '0')
        {
            mine[x][y] = '1';
            count--;
        }
    }
}

第4步:获取周围雷数

这是扫雷的核心算法。由于使用了扩大2格的数组,当玩家在坐标 (x, y) 处排查时,其周围8个格子的合法索引必定存在。只需将这8个格子的字符ASCII值相加,再减去8倍的 '0' 即可得到整数型的雷数。

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    return (mine[x - 1][y] +
            mine[x - 1][y - 1] +
            mine[x][y - 1] +
            mine[x + 1][y - 1] +
            mine[x + 1][y] +
            mine[x + 1][y + 1] +
            mine[x][y + 1] +
            mine[x - 1][y + 1] - 8 * '0');
}

第5步:实现排查交互逻辑

在 FindMine 函数中,通过循环不断接收用户输入的坐标。如果输入合法且未被炸死,则调用 GetMineCount 更新 Show Board 并打印;若输入错误或触发炸弹,则给出提示并跳出循环。获胜条件是累计排查的安全格子数等于总格子数减去雷数。

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0, y = 0, win = 0;

    while (win < row * col - EASY_COUNT)
    {
        printf("请输入排查的坐标: ");
        scanf("%d%d", &x, &y);

        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("很遗憾,你被炸死了\n");
                DisplayBoard(mine, row, col); // 揭示雷的位置
                break;
            }
            else
            {
                int count = GetMineCount(mine, x, y);
                show[x][y] = count + '0';     // 将数字转为字符存入显示板
                DisplayBoard(show, row, col);
                win++;
            }
        }
        else
        {
            printf("坐标有误,请重新输入!\n");
        }
    }

    if (win == row * col - EASY_COUNT)
    {
        printf("恭喜你,排雷成功!\n");
        DisplayBoard(mine, row, col);
    }
}

第6步:组装主控流程

在 test.c 中包含头文件,实现菜单显示与 srand 种子初始化,确保每次运行布雷都是随机的。

// test.c
void game()
{
    char mine[ROWS][COLS];
    char show[ROWS][COLS];

    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    SetMine(mine, ROW, COL);
    DisplayBoard(show, ROW, COL); // 初始打印空白棋盘
    FindMine(mine, show, ROW, COL);
}

int main()
{
    srand((unsigned int)time(NULL));
    // 此处应包含 menu 循环调用 logic
    game();
    return 0;
}

简要总结

本示例通过分离数据存储与显示界面的思路,巧妙地避开了复杂的内存管理与复杂的数据结构。利用C语言的指针与数组特性,实现了高效的周边检索,是初学者理解多维数组应用及游戏底层逻辑的经典范例。以上就是C语言实现经典扫雷小游戏的详细内容,更多关于C语言开发入门的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表