目录
一、代码整体结构
代码分为三个文件:
-
game.h
:声明常量、函数原型及头文件引用。 -
game.c
:实现游戏核心逻辑(初始化棋盘、埋雷、排雷等)。 -
main.c
:处理用户交互及游戏主循环。
二、关键常量定义
在 game.h
文件中,定义了几个重要的常量:
#define Mine 10
#define row 9
#define col 9
#define rows row+2
#define cols col+2
Mine
代表雷的数量,这里设置为 10 颗。row
和col
定义了游戏棋盘的实际大小,是 9×9 的网格。rows
和cols
则是在实际棋盘周围扩展了一圈的大小,目的是为了在计算雷的数量时避免越界问题。
1、函数声明与实现
(1)初始化棋盘函数:InitBoard
void InitBoard(char board[rows][cols], int r, int c, char set) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
board[i][j] = set;
}
}
}
这个函数用于初始化游戏棋盘。它接受一个二维字符数组 board
、棋盘的行数 r
、列数 c
以及一个初始化字符 set
。通过两层循环遍历整个棋盘,将每个元素都设置为 set
。在游戏中,我们用它来初始化雷盘(初始值为 '0'
)和显示盘(初始值为 '*'
)。
(2)显示棋盘函数:DisplayBoard
void DisplayBoard(char board[rows][cols], int r, int c) {
printf("------扫雷游戏------\n");
for (int i = 0; i <= r; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= r; i++) {
printf("%d ", i);
for (int j = 1; j <= c; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
}
该函数负责在控制台显示游戏棋盘。首先打印表头,包括列号;然后逐行打印棋盘内容,每行开头是行号,接着是该行的每个格子内容。这样玩家就能直观地看到游戏棋盘的状态。
(3)设置雷的函数:SetMine
void SetMine(char board[rows][cols], int r, int c) {
int count = Mine;
while (count) {
int x = rand() % r + 1;
int y = rand() % c + 1;
if (board[x][y] == '0') {
board[x][y] = '1';
count--;
}
}
}
这个函数的作用是在棋盘上随机布置雷。它使用 rand()
函数生成随机数来确定雷的位置(x
和 y
)。如果随机生成的位置上当前没有雷(board[x][y] == '0'
),就将该位置设置为雷(board[x][y] = '1'
),并减少剩余雷的数量 count
,直到布置完所有的雷。
(4)计算周围雷数量的函数:GetMine
int GetMine(char mine[rows][cols], char show[rows][cols], int x, int y) {
int count = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if (mine[i][j] == '1') {
count++;
}
}
}
return count;
}
GetMine
函数用于计算某个位置周围的雷的数量。它通过遍历目标位置(x
, y
)周围九宫格内的每个格子,检查雷盘 mine
中对应位置是否为雷(mine[i][j] == '1'
),如果是则计数器 count
加一,最后返回周围雷的总数。
void FindMine(char mine[rows][cols], char show[rows][cols], int r, int c) {
int x = 0;
int y = 0;
int win = 0;
while (win < r * c - Mine) {
printf("请输入需要排查的坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= r && y >= 1 && y <= c) {
if (mine[x][y] == '1') {
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, row, col);
break;
} else {
int count = GetMine(mine, show, x, y);
show[x][y] = count + '0';
DisplayBoard(show, row, col);
win++;
}
} else {
printf("非法坐标,请重新输入\n");
}
}
}
FindMine
函数是游戏的核心逻辑。它通过一个循环不断让玩家输入要排查的坐标。如果输入的坐标合法且该位置是雷,游戏结束并显示雷盘;如果不是雷,则计算该位置周围雷的数量,将数量显示在显示盘上,并增加胜利计数器 win
。当胜利计数器达到总格子数减去雷的数量时,玩家获胜。
三、游戏流程控制:main.c
在 main.c
中,meau
函数用于显示游戏菜单,让玩家选择开始游戏或退出游戏。game
函数则负责调用前面定义的各个函数,完成游戏的初始化、设置雷、显示棋盘和排查雷等操作。main
函数通过一个 do-while
循环,根据玩家的选择来控制游戏的开始和结束。
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
meau();
printf("请选择:");
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
这里还使用 srand((unsigned int)time(NULL))
初始化随机数种子,确保每次运行游戏时雷的分布都是随机的。
四、全部代码
1、game.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define Mine 10
#define row 9
#define col 9
#define rows row+2
#define cols col+2
void InitBoard(char board[rows][cols], int r, int c, char set);
void DisplayBoard(char board[rows][cols], int r, int c);
void SetMine(char board[rows][cols], int r, int c);
void FindMine(char mine[rows][cols],char show[rows][cols], int r, int c);
2、game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[rows][cols], int r, int c, char set) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
board[i][j] = set;
}
}
}
void DisplayBoard(char board[rows][cols], int r, int c) {
printf("------扫雷游戏------\n");
for (int i = 0; i <= r; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= r; i++) {
printf("%d ", i);
for (int j = 1; j <= c; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void SetMine(char board[rows][cols], int r, int c) {
int count = Mine;
while (count) {
int x = rand() % r + 1;
int y = rand() % c + 1;
if (board[x][y] = '0') {
board[x][y] = '1';
count--;
}
}
}
int GetMine(char mine[rows][cols],char show[rows][cols], int x, int y) {
int count = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if (mine[i][j] == '1') {
count++;
}
}
}
return count;
}
void FindMine(char mine[rows][cols],char show[rows][cols], int r, int c) {
int x = 0;
int y = 0;
int win = 0;
while (win < r * c - Mine) {
printf("请输入需要排查的坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= r && y >= 1 && y <= c) {
if (mine[x][y] == '1') {
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, row, col);
break;
}
else {
int count = GetMine(mine, show, x, y);
show[x][y] = count + '0';
DisplayBoard(show, row, col);
win++;
}
}
else {
printf("非法坐标,请重新输入\n");
}
}
}
3、mian.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void meau() {
printf("***************************\n");
printf("******* 1. paly ********\n");
printf("******* 0. exit ********\n");
printf("***************************\n");
}
void game() {
char mine[rows][cols] = { 0 };
char show[rows][cols] = { 0 };
InitBoard(mine, rows, cols, '0');
InitBoard(show, rows, cols, '*');
DisplayBoard(show, row, col);
SetMine(mine, row, col);
FindMine(mine,show, row, col);
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
meau();
printf("请选择:");
scanf("%d",&input);
switch (input) {
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
五、总结与拓展
通过这段代码,我们实现了一个基本的扫雷游戏。它涵盖了 C 语言中的数组操作、函数调用、循环结构、条件判断以及随机数生成等知识点。如果想要进一步拓展这个游戏,可以增加一些功能,比如标记雷的功能、更高难度的棋盘设置、游戏计时等。希望大家通过对这段代码的学习,对 C 语言编程有更深入的理解,也能从编写游戏的过程中获得乐趣。