C 语言实现经典扫雷游戏|从零到一完整教程(含详细注释 + 源码)

C 语言实现经典扫雷游戏|从零到一完整教程(含详细注释 + 源码)

大家好,今天带大家用纯 C 语言从零实现经典的扫雷游戏!这个项目非常适合 C 语言新手,能巩固二维数组、函数封装、随机数、逻辑判断等核心知识点,代码完整可直接运行,保姆级教学,新手也能轻松学会~

一、游戏需求分析

我们要实现的扫雷功能:

  1. 9×9 的游戏棋盘(外围加一圈安全边距,防止坐标越界)
  2. 随机布置 80 个地雷(难度可自定义)
  3. 输入坐标排查地雷:踩到雷直接游戏结束,没踩到显示周围雷数
  4. 排查完所有非雷区域,游戏胜利

二、整体设计思路

扫雷需要两个二维数组,分工明确:

  1. mine 数组:存放地雷布局('0'= 无雷,'1'= 有雷),不对玩家展示
  2. show 数组:玩家看到的界面('*'= 未排查,数字 = 周围雷数)
  3. 函数模块化:初始化棋盘、布置雷、打印棋盘、排查雷

三、分模块代码实现

我们采用多文件编程,代码更清晰:

  • game.h:头文件(宏定义、函数声明、头文件包含)
  • game.c:游戏功能函数实现
  • test.c:主函数、游戏逻辑入口

    模块 1:头文件 game.h

    统一管理宏定义和函数声明,方便后期修改游戏参数

  • #pragma once // 防止头文件重复包含

  • #include <stdio.h>

  • #include <time.h>

  • #include <stdlib.h> // rand、srand函数需要 // 宏定义(修改这里就能调整棋盘大小/雷数)

  • #define ROW 9 // 实际游戏行

  • #define COL 9 // 实际游戏列

  • #define ROWS ROW+2 // 带边距行(防止越界)

  • #define COLS COL+2 // 带边距列

  • #define EASY_COUNT 80// 简易模式雷数 // 函数声明

  • void menu(); // 菜单

  • void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); // 初始化棋盘

  • void SetMine(char board[ROWS][COLS], int row, int col); // 布置地雷

  • void DisplayBoard(char board[ROWS][COLS], int row, int col); // 打印棋盘

  • void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); // 排查地雷

  • 模块 2:游戏函数实现 game.c

    包含所有游戏核心功能,代码带详细注释

  • #define _CRT_SECURE_NO_WARNINGS
    #include "game.h"

    // 1. 游戏菜单
    void menu()
    {
        printf("----------------------\n");
        printf("------ 0. 退出 -------\n");
        printf("------ 1. 开始 -------\n");
        printf("----------------------\n");
    }

    // 2. 初始化棋盘:把数组所有元素设置为指定字符set
    void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
    {
        int i = 0;
        for (i = 0; i < rows; i++)
        {
            int j = 0;
            for (j = 0; j < cols; j++)
            {
                board[i][j] = set;
            }
        }
    }

    // 3. 随机布置地雷
    void SetMine(char board[ROWS][COLS], int row, int col)
    {
        int count = EASY_COUNT;  // 需要布置的雷数
        while (count)
        {
            // 生成1~9的随机坐标(避开边距)
            int x = rand() % row + 1;
            int y = rand() % col + 1;

            if (board[x][y] == '0')  // 该位置无雷,才布置
            {
                board[x][y] = '1';
                count--;
            }
        }
    }

    // 4. 打印棋盘(带坐标提示,方便玩家输入)
    void DisplayBoard(char board[ROWS][COLS], int row, int col)
    {
        // 打印列号
        int i = 0;
        int j = 0;
        printf("  ");
        for (j = 1; j <= col; j++)
        {
            printf("%d ", j);
        }
        printf("\n");

        // 打印行号+棋盘内容
        for (i = 1; i <= row; i++)
        {
            printf("%d ", i);
            for (j = 1; j <= col; j++)
            {
                printf("%c ", board[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }

    // 5. 计算(x,y)坐标周围8个格子的地雷数量
    int GetMineCount(char board[ROWS][COLS], int x, int y)
    {
        // 字符'0'=48,'1'=49,相加后减8*'0',直接得到数字
        return board[x - 1][y - 1] +
               board[x - 1][y] +
               board[x - 1][y + 1] +
               board[x][y - 1] +
               board[x][y + 1] +
               board[x + 1][y - 1] +
               board[x + 1][y] +
               board[x + 1][y + 1] -
               8 * '0';
    }

    // 6. 排查地雷(核心逻辑)
    void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
        int x = 0;
        int y = 0;
        int win = 0;  // 已排查的非雷格子数

        // 总非雷数 = 总格子 - 雷数
        while (win < row * col - EASY_COUNT)
        {
            printf("请输入排查坐标(行 列):");
            scanf("%d %d", &x, &y);

            // 1. 判断坐标合法性
            if (x >= 1 && x <= row && y >= 1 && y <= col)
            {
                // 2. 踩到雷 → 游戏结束
                if (mine[x][y] == '1')
                {
                    printf("💣 很遗憾,你踩到地雷了!\n");
                    DisplayBoard(mine, ROW, COL);  // 展示雷区
                    break;
                }
                // 3. 没踩到雷 → 计算周围雷数
                else
                {
                    if (show[x][y] == '*')  // 未被排查过
                    {
                        // 把数字存入show数组
                        show[x][y] = GetMineCount(mine, x, y) + '0';
                        DisplayBoard(show, ROW, COL);
                        win++;
                    }
                    else
                    {
                        printf("⚠️ 该坐标已排查过!\n");
                    }
                }
            }
            else
            {
                printf("❌ 坐标非法,请重新输入!\n");
            }
        }

        // 所有非雷都排查完 → 胜利
        if (win == row * col - EASY_COUNT)
        {
            printf("🎉 恭喜你,扫雷成功!\n");
        }
    }
    模块 3:主逻辑 test.c
    游戏入口,控制开始 / 退出

  • #define _CRT_SECURE_NO_WARNINGS
    #include "game.h"

    // 游戏核心流程
    void game()
    {
        // 定义两个数组
        char mine[ROWS][COLS] = { 0 };   // 存放雷
        char show[ROWS][COLS] = { 0 };   // 展示界面

        // 1. 初始化数组
        InitBoard(mine, ROWS, COLS, '0');  // mine全初始化为'0'
        InitBoard(show, ROWS, COLS, '*');  // show全初始化为'*'

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

        // 调试用:打印雷区(正式游戏可注释)
        // DisplayBoard(mine, ROW, COL);

        // 3. 打印玩家界面
        DisplayBoard(show, ROW, COL);

        // 4. 排查地雷
        FindMine(mine, show, ROW, COL);
    }

    // 主函数
    int main()
    {
        int input = 0;
        srand((unsigned int)time(NULL));  // 设置随机数种子

        // 循环菜单
        do
        {
            menu();
            printf("请选择:");
            scanf("%d", &input);
            switch (input)
            {
            case 0:
                printf("👋 游戏退出\n");
                break;
            case 1:
                printf("🎮 开始扫雷!\n");
                game();
                break;
            default:
                printf("❌ 选择错误,请重新输入!\n");
                break;
            }
        } while (input);

        return 0;
    }
    四、关键知识点讲解
    1. 为什么要用 ROWS=ROW+2?
    9×9 的棋盘,排查边缘坐标时(比如(1,1)),需要访问(0,0),会数组越界崩溃。
    加一圈边距,所有排查逻辑都不用判断边界,代码更简单安全!
    2. 字符数字计算原理
    字符'0'的 ASCII 码是 48,'1'是 49
    8 个格子相加后,减去8*'0',直接得到整数雷数
    最后加'0',转回字符存入数组
    3. 随机数布置地雷
    rand()生成随机数
    rand()%9+1 → 生成 1~9 的合法坐标
    srand((unsigned int)time(NULL)):用时间戳做种子,保证每次雷区不同
    五、运行效果
    菜单界面
    玩家初始界面(全*)
    输入坐标排查,显示数字
    踩雷 → 展示全部雷区
    排完所有非雷 → 游戏胜利
    六、可扩展优化方向
    添加标记地雷功能(输入特殊符号标记雷)
    实现自动展开(点开 0 周围无雷,自动展开一片)
    增加难度选择(简单 / 中等 / 困难)
    美化界面(加颜色、分隔线)
    七、总结
    这个扫雷项目完美覆盖了 C 语言数组、函数、循环、随机数、逻辑判断等核心知识点,代码结构清晰、注释详细,非常适合新手练习。
    跟着教程一步步敲,你不仅能写出可运行的游戏,更能理解模块化编程的思想,这对后续学习 C 语言、数据结构都非常有帮助!
    需要完整源码文件的同学可以直接复制代码,创建三个文件即可运行~有问题欢迎评论区交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

影视飓风TIM

无限进步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值