介绍:
众所周知,扫雷游戏是一款经典的益智游戏。今天我将介绍使用C语言来实现一个命令行版本的扫雷游戏,通过控制台输入和输出来进行游戏。
先给出运行截图:
一.首先,先把程序的框架打好。考虑到要判断用户的输入,可以用switch(),利用while()可以实现循环输入。
int input = 0;
do {
printf("请输入您的选择:\n");
menu();
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("您输入的值有误\n");
break;
}
} while (input);
二.实现简单的菜单函数,采用输出语句即可。
void menu() {
printf("----------------------\n");
printf("----0.exit 1.play----\n");
printf("----------------------\n");
}
三.接着实现游戏主体函数game()。我们先考虑游戏需要的几个函数,对应 的实现之后在进行。
需要设置雷的位置,打印出雷区的状态。
然而在进行game()实现之前,我们先做一点准备工作,宏定义几个值,便于之后的操作,扫雷的雷区大小,雷的个数先利用宏定义给出。为了防止越界ROWS,COLS在雷区上+2.
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define easy 10
1.我们先创建了两个二维字符数组 mine
和 show
,分别用于存放雷区的真实信息和显示信息。使用 InitMine()
函数将它们初始化为相应的值,用'*'表示扫雷的背景。
char mine[ROWS][COLS] = { 0 };//存放布置雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出雷的信息
InitMine(mine, ROW, COL, '0');//初始化
InitMine(show, ROW, COL, '*');
2. 调用 DisplayMine()
函数打印初始的雷区显示状态。
3.使用 SetMine()
函数在雷区中随机设置雷的位置。
4.调用 DisplayMine()
函数打印设置雷后的雷区显示状态。
5.调用 FindMine()
函数进入真正的游戏流程,玩家开始输入坐标来排查雷区。
char mine[ROWS][COLS] = { 0 };//存放布置雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出雷的信息
InitMine(mine, ROW, COL, '0');//初始化
InitMine(show, ROW, COL, '*');
//ShowMine(mine, ROW, COL);//打印函数
DisplayMine(show, ROW, COL);
SetMine(mine, ROW, COL);
//DisplayMine(mine, ROW, COL);
//排雷
FindMine(mine, show, ROW, COL);
四.我们接着来实现初始化的函数InitMine(
char mine[ROWS][COLS], int row, int col, char ret)
实现思路:
- 使用双重循环遍历雷区的每一个格子。
- 在循环中,将每个格子的值设置为指定的字符
ret
。
这段代码的作用是对雷区进行初始化,将所有格子的值设置为指定字符。通过调用这个函数,可以将雷区的状态重置为初始状态,以便进行新的游戏。
void InitMine(char mine[ROWS][COLS], int row, int col, char ret) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
mine[i][j] = ret;
}
}
}
五.然后实现打印函数void DisplayMine(char mine[ROWS][COLS], int row, int col)。
实现思路:
- 使用双重循环遍历雷区的每一个格子。
- 在循环中,使用
printf
函数按照一定格式打印每个格子的值。 - 在外层循环中,额外打印一行列标号。
- 在内层循环中,首先打印行标号,然后打印每个格子的值,再打印换行符。
这段代码的作用是打印雷区的状态,以方便玩家在命令行中查看雷区的布局和已经排查过的格子的状态,同时该函数可以提醒用户对应的位置是哪里。
void DisplayMine(char mine[ROWS][COLS], int row, int col) {
for (int k = 0; k <= col; k++)
printf("%d ", k);
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {
printf("%c ", mine[i][j]);
}
printf("\n");
}
}
六.然后实现设置雷的函数void SetMine(char mine[ROWS][COLS], int row, int col)。
实现思路:
- 使用一个
count
变量来记录还需要设置的雷的数量。 - 使用
rand()
函数生成随机数来确定雷的位置。同时也要记得随机数种子的设置。 - 在循环中,随机生成
x
和y
坐标来表示雷的位置。 - 检查雷区中对应位置是否已经设置了雷,如果没有则将该位置设为雷,同时将
count
减一。
这段代码的作用是在雷区中随机设置一定数量的雷。通过调用这个函数,可以让雷在雷区中的位置变得随机,增加游戏的难度和变化性。
void SetMine(char mine[ROWS][COLS], int row, int col) {
int count = easy;
while (count) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0') {
mine[x][y] = '1';
count--;
}
}
}
七.再来实现统计雷的个数的函数int countmine(char mine[ROWS][COLS], int x, int y)。
实现思路:
- 遍历指定位置周围的八个格子。
- 将周围八个格子的值相加,得到雷的数量。
- 使用字符的 ASCII 值减去 ‘0’ 的 ASCII 值,将字符转换为整数。
这段代码的作用是计算指定位置周围的雷的数量。通过调用这个函数,可以根据指定位置的坐标来获取该位置周围雷的数量,以便在游戏中进行排雷判断或显示周围雷的数量。
int countmine(char mine[ROWS][COLS], int x, int y) {
return (mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] -
8 * '0');
}
八.最后我们实现排雷代码void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)。
实现思路:
- 使用一个循环,直到游戏结束才退出。
- 通过
printf
函数要求玩家输入要排雷的位置的坐标。 - 使用
scanf
函数接收玩家输入的坐标。 - 检查玩家输入的坐标是否合法,即坐标是否在雷区范围内。
- 如果坐标已经被排查过,则提示不能重复排查。
- 如果坐标上有雷,则游戏结束,输出失败的提示信息。
- 如果坐标上没有雷,则更新展示雷区状态,将周围雷的数量显示在该坐标上。
- 调用
DisplayMine
函数显示更新后的雷区状态。 - 检查是否达到了排雷成功的条件,即已排除所有非雷的格子。
- 如果成功排雷,则输出成功的提示信息,并结束游戏。
这段代码的作用是对雷区进行排雷操作。通过循环接受玩家输入的坐标并判断排雷情况,根据不同的情况输出相应的提示信息进行交互。
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x = 0;
int y = 0;
int win = 0;
while (1) {
printf("请输入您要排雷的位置:\n");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (show[x][y] != '*') {
printf("该坐标已经被排查过了,不能重复排查\n");
}
else {
if (mine[x][y] == '1') {
printf("很遗憾,您被炸死了\n");
break;
}
else {
win++;
int count = countmine(mine, x, y);
show[x][y] = count + '0';
DisplayMine(show, ROW, COL);
if (win == row * col - easy)
{
printf("恭喜你,排雷成功\n");
break;
}
}
}
}
else {
printf("您输入的值有误,请重新输入\n");
}
}
}
这份扫雷代码包含了多个函数来实现基本的扫雷游戏功能。下面是各个函数的功能总结:
DisplayMine()
: 用于显示雷区的状态,包括行和列的标号。SetMine()
: 在雷区中随机设置一定数量的雷。countmine()
: 计算指定位置周围的雷的数量。FindMine()
: 进行雷区的排雷操作。
代码中的主要思路是使用二维数组来表示雷区,并根据用户的输入和判断进行相应的处理。主要的流程如下:
- 初始化雷区和展示区的二维数组。
- 使用
SetMine()
随机设置雷的位置。 - 进入排雷循环,通过
FindMine()
接受用户输入的坐标并进行处理。 - 检查当前坐标是否在合法范围内,是否已经排查过或是雷。
- 根据情况更新展示区的状态,并显示雷区状态。
- 检查是否达到了排雷成功或失败的条件,若成功或失败则输出相应的提示信息并结束游戏。
总结:
总体而言,这段代码实现了一个简单的扫雷游戏,提供了雷区的生成、排雷和输赢判断功能。
同时也还存在一些待完善的功能,比如可以利用递归实现在玩家排查出一个位置后,根据周围的地雷数量更新显示区的信息,并继续排查周围的位置,直到没有相邻的非地雷位置为止。这样,玩家可以一次性排查出一片区域,提高游戏的效率和体验。本代码的难度相对而言要低一点,认真思考过后,自己动手敲一敲。