C语言实现扫雷:从思路到源码的详细教程

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

本文详细解析如何使用C语言从零开始实现经典的Windows扫雷游戏。文章涵盖了项目结构设计、二维数组的巧妙运用(通过扩大数组防止越界)、棋盘初始化与打印、随机布雷算法以及坐标排查逻辑,并提供了包含game.h、game.c和test.c的完整可运行代码。

设计思路与核心逻辑

在实现扫雷游戏之前,首先需要理清数据存储的方式。扫雷棋盘通常为9×9大小,若直接定义 char mine[9][9] 来存储地雷信息,在处理边界格子周围的雷数统计时,访问相邻8个位置极易发生数组越界。为了解决这一问题,我们将实际使用的棋盘定义为11×11的二维数组,即 ROWS (ROW + 2) 和 COLS (COL + 2),而玩家看到的区域仅为中间的9×9部分。这种“扩边”策略能有效避免越界检测逻辑。

同时,为了区分“地雷信息”和“玩家排查出的状态”,我们需要两个独立的数组:

  • char mine[11][11]:用于后台存储雷的位置,字符'0'表示无雷,'1'表示有雷。
  • char show[11][11]:用于展示给玩家的界面,初始状态全部填充'*'表示未探索,当安全时该位置将显示周围一圈的雷数(数字字符)。

游戏的核心流程包括:初始化棋盘 → 随机布置地雷 → 玩家输入坐标排查 → 判定胜负。

具体操作顺序

第1步:构建游戏主框架与菜单

目的:提供重复游戏的循环机制和用户交互入口。
文件:test.c
动作:使用 do-while 循环包裹菜单和 switch-case 结构,实现选择“1”开始游戏、“0”退出游戏的功能。在游戏开始前调用 srand((unsigned int)time(NULL)) 以生成不同的随机序列。

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

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL)); // 必须放在循环外
	do {
		menu();
		printf("请选择(1/0):>");
		scanf("%d", &input);
		switch (input)
		{
		case 1: game(); break;
		case 0: printf("退出游戏\n"); break;
		default: printf("选择错误!\n"); break;
		}
	} while (input); // 输入非0值继续
	return 0;
}

第2步:定义棋盘尺寸与头文件声明

目的:统一管理常量,方便后续修改棋盘难度。
文件:game.h
参数: #define ROW 9, #define COL 9 为实际大小;#define ROWS (ROW + 2), #define COLS (COL + 2) 为物理数组大小;#define EASY_COUNT 10 为地雷总数。
函数声明: 包括初始化 init_board、打印 show_board、布雷 set_mine 和排查 find_mine。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 9
#define COL 9
#define ROWS (ROW + 2)
#define COLS (COL + 2)
#define EASY_COUNT 10

// ... 函数原型声明 ...

第3步:初始化与打印棋盘

目的:准备空白的游戏面板。
文件:game.c
动作:遍历整个11×11的物理数组。对于mine数组填入字符'0',对于show数组填入字符'*'。打印函数只遍历1到ROW及1到COL的区域,并在输出两侧添加行号和列标以提升可读性。

// 打印效果示意
/*
------------扫雷------------
 0 1 2 3 4 5 6 7 8 9
 1 * * * * * * * * * *
 2 * * * * * * * * * *
 ...
*/

第4步:随机布置地雷

目的:在mine数组中随机生成指定数量的'1'。
文件:game.c
动作:使用 while(count) 循环。每次 x = rand() % row + 1,y = rand() % col + 1 生成有效范围内的坐标。若该位置当前为'0',则置为'1'并将计数器减1,直至布完所有雷。此方法简单直观,但效率较低(存在重复生成的概率),对于小规模棋盘足够适用。

第5步:排查雷与计算周边雷数

目的:处理用户输入,更新show数组并判定输赢。
文件:game.c
动作: 1. 检查坐标合法性(1~9)。
2. 检查该坐标是否已被排查过(是否为'*')。
3. 若踩中雷(mine[x][y]=='1'),游戏结束,显示全图。
4. 若安全,计算周围8个格子的雷总数。由于mine数组存的是字符,利用ASCII码差值:sum = 周围字符相加 - 8*'0'。计算结果即为真实雷数。
5. 将 count+'0' 存入 show[x][y] 并打印。
6. 胜利条件:已找到的安全格子数等于总格子数减去雷数(win == row*col - EASY_COUNT)。

static int get_mine_count(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';
}

完整代码汇总

以下是整合后的三个主要源文件,可直接编译运行(需注意编译器对 _CRT_SECURE_NO_WARNINGS 的支持情况)。

game.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 9
#define COL 9
#define ROWS (ROW + 2)
#define COLS (COL + 2)
#define EASY_COUNT 10

void init_board(char arr[ROWS][COLS], int rows, int cols, char set);
void show_board(char arr[ROWS][COLS], int row, int col);
void set_mine(char mine[ROWS][COLS], int row, int col);
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void init_board(char arr[ROWS][COLS], int rows, int cols, char set)
{
	int i, j;
	for (i = 0; i < rows; ++i)
		for (j = 0; j < cols; ++j)
			arr[i][j] = set;
}

void show_board(char arr[ROWS][COLS], int row, int col)
{
	int i, j;
	printf("------------扫雷------------\n");
	for (i = 0; i <= col; ++i) printf("%d ", i); // 打印列标
	printf("\n");
	for (i = 1; i <= row; ++i)
	{
		printf("%d ", i); // 打印行号
		for (j = 1; j <= col; ++j)
			printf("%c ", arr[i][j]);
		printf("\n");
	}
	printf("------------扫雷------------\n");
}

void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT, x, y;
	while (count)
	{
		x = rand() % row + 1;
		y = rand() % col + 1;
		if ('0' == mine[x][y]) { mine[x][y] = '1'; --count; }
	}
}

static int get_mine_count(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';
}

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y, win = 0;
	while (win < row * col - EASY_COUNT)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if ('*' == show[x][y])
			{
				if ('1' == mine[x][y])
				{
					printf("很遗憾,你被炸死了\n");
					show_board(mine, row, col); break;
				}
				else
				{
					int count = get_mine_count(mine, x, y);
					show[x][y] = count + '0';
					show_board(show, row, col);
					++win;
				}
			}
			else printf("该坐标已被排查\n");
		}
		else printf("坐标非法,重新输入\n");
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		show_board(mine, row, col);
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

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

void game(){
	char mine[ROWS][COLS] = {0};
	char show[ROWS][COLS] = {0};
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	set_mine(mine, ROW, COL);
	show_board(show, ROW, COL); // 不显示mine的内容
	find_mine(mine, show, ROW, COL);
}

int main(){
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请选择(1/0):>");
		scanf("%d", &input);
		switch (input){
		case 1: game(); break;
		case 0: printf("退出游戏\n"); break;
		default: printf("选择错误!\n"); break;
		}
	} while (input);
	return 0;
}

以上就是C语言实现经典windows游戏扫雷的示例代码的详细内容,更多关于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 算法库。