扫雷游戏的实现(详解)

C/C++
175
0
0
2024-05-01

首先我们来看一下扫雷游戏

 这是一个扫雷游戏,所以我们要做的第一步就是把这个棋盘初始化并打印出来。这就用到了二维数组,初始化棋盘之后我们就要把雷布置在棋盘里面,然后进行排查雷,这是我们实现扫雷游戏的一个大体思维框架。

还需要注意的是,我们创建游戏的过程中需要用到两个源文件(game.c test.c)和一个头文件(game.h),在头文件中包含了程序所需的各种头文件并且实现对各种函数的声明,而源文件test.c用于引用函数,game.c实现函数。这样做的目的是为了各个文件可以处理各自模块的功能,增强逻辑性和代码的清晰度,使得可读性更高。

接下来让我们一起实现这个扫雷游戏吧。

首先我们将游戏初始化。

代码语言:javascript

复制

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//生成随机数
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择:>\n");
		}
	} while (input);
	return 0;
}
首先打印一个菜单,让玩家选择,如果选择一,就进入game(),选择0就退出游戏,输入其他的数字则重新选择。

 接下来我们完成game()的内容,也就是扫雷游戏中最主要的内容,那么首先我们就将棋盘打印出来,假设我们打印出9*9的棋盘,我们在game.h里面声明棋盘的行和列,然后在test.c里面调用。

代码语言:javascript

复制

//布局9*9方格
#define ROW 9
#define COL 9
//多出隐藏的两行两列用来补全边缘棋盘6个方格凑9个方便计算
#define ROWS ROW+2
#define COLS COL+2

代码语言:javascript

复制

char mine[ROWS][COLS];
char show[ROWS][COLS];
我们再将棋盘进行初始化并打印 ,在game.c里面进行。初始化之后我们打印棋盘让自己看一下,在test.c里面调用DisplayBoard。

代码语言:javascript

复制

//初始化
void InitBoard(char board[ROWS][COLS],int rows,int cols);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

代码语言:javascript

复制

InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);

代码语言:javascript

复制

void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
	//初始化棋盘
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;//set放入想要的字符
		}
	}
}

代码语言:javascript

复制

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("--------扫雷---------\n");//使得棋盘更加清晰
	for (i = 0; i <= col; i++)//i为一的话棋盘没有对齐,所以从0开始右移一位
	{
		printf("%d ", i); 
	}
	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");
}

 上图是我们看到的结果。既然我们初始化棋盘并且打印了,我们就开始在棋盘上布置雷,假设我们布置10个雷。在game.h中声明。

代码语言:javascript

复制

//布置10个雷
#define EASY_COUNT 10
//放置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
在test.c中进行调用,

代码语言:javascript

复制

SetMine(mine, ROW, COL);//放置雷
在game.c中进行实现,这里调用rand函数生成随机数,所以我们要在game.h中包含头文件#include<time.h> #include<string.h> 并且在test.c里面将随机数生成。

代码语言:javascript

复制

srand((unsigned int)time(NULL));//生成随机数

代码语言:javascript

复制

void SetMine(char mine[ROWS][COLS], int row, int col) 
{
	int count = EASY_COUNT;//将雷的数量确定
	while (count)//将雷循环布置,每次布置一个雷count--,count为0时跳出去
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;//将雷随机生成在9*9的棋盘上
		if (mine[x][y] == '0')//判断这个位置有没有雷
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
 布置好雷后我们将棋盘打印出来,这时我们将DisplayBoard函数放在SetMine函数下面,打印的结果如下图,这是我们布置好的雷,当然我们不能让玩家看见啊,不然还得了啊(捂脸),所以我们将DisplayBoard函数注释掉。

 现在我们就来到了最关键的也是最重要的一步了,我们开始排雷。首先依旧是在game.h中进行声明。

代码语言:javascript

复制

//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
 test.c中调用。

代码语言:javascript

复制

FindMine(mine,show,ROW, COL);//排查雷,两个棋盘排雷
 game.c实现,首先我们进行while循环,循环条件是没踩中的地方小于没有雷的地方。玩家输入坐标,函数进行判断是非合法,如果合法再判断是否踩雷,踩中雷则跳出循环,打印棋盘,游戏结束。如果没猜中雷就统计一下该坐标周围有几个雷,这时我们定义一个函数GetMineCount,c来接收返回值。这里需要用到ASCII码的知识,该坐标周围8个坐标的ASCII码值减去‘0’的ASCII码值得到周围有几个雷。如果我们排雷成功,即win=row*col-EASY_COUNT,则打印"恭喜你,排雷成功"。

代码语言:javascript

复制

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';
}

代码语言:javascript

复制

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);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入的坐标在不在棋盘里面
		{
			if (mine[x][y] == '1')//判断是否踩雷
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else//不是雷,统计该坐标周围有几个雷
			{
				int c=GetMineCount(mine, x, y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);//将排查完的信息打印
				win++;
			}
		}
		else
		{
			printf("该坐标非法,请重新输入:>\n");
		}
	}
	if (win = row * col - EASY_COUNT)//将雷排完了
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);//打印出来最后结果
	}
}
 到这里我们的游戏就实现了,有兴趣的小伙伴可以去试一下。以下是全部代码。

代码语言:javascript

复制

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>//srand所需要的头文件
#include<string.h>//srand所需要的头文件

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EASY_COUNT 10
//初始化
void InitBoard(char board[ROWS][COLS],int rows,int cols);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//放置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


#define _CRT_SECURE_NO_WARNINGS 1
#include"扫雷.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
	//初始化棋盘
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;//set放入想要的字符
		}
	}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("--------扫雷---------\n");//使得棋盘更加清晰
	for (i = 0; i <= col; i++)//i为一的话棋盘没有对齐,所以从0开始右移一位
	{
		printf("%d ", i); 
	}
	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");
}
void SetMine(char mine[ROWS][COLS], int row, int col) 
{
	int count = EASY_COUNT;//将雷的数量确定
	while (count)//将雷循环布置,每次布置一个雷count--,count为0时跳出去
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;//将雷随机生成在9*9的棋盘上
		if (mine[x][y] == '0')//判断这个位置有没有雷
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
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';
}
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);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入的坐标在不在棋盘里面
		{
			if (mine[x][y] == '1')//判断是否踩雷
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else//不是雷,统计该坐标周围有几个雷
			{
				int c=GetMineCount(mine, x, y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);//将排查完的信息打印
				win++;
			}
		}
		else
		{
			printf("该坐标非法,请重新输入:>\n");
		}
	}
	if (win = row * col - EASY_COUNT)//将雷排完了
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);//打印出来最后结果
	}
}


#define _CRT_SECURE_NO_WARNINGS 1
#include"扫雷.h"
void menu()
{
	printf("*********************************\n");
	printf("********   1.play        ********\n");
	printf("********   0.exit        ********\n");
	printf("*********************************\n");
}
void game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	InitBoard(mine, ROWS, COLS,'0');
	InitBoard(show, ROWS, COLS,'*');
	DisplayBoard(show, ROW, COL);//给玩家看到的棋盘,所以是9*9
	SetMine(mine, ROW, COL);//放置雷
	//DisplayBoard(mine, ROW, COL);//给自己看的棋盘,不需要打印
	FindMine(mine,show,ROW, COL);//排查雷,两个棋盘排雷
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//生成随机数
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择:>\n");
		}
	} while (input);
	return 0;
}
非常感谢烙铁们的阅读,让我们共同进步。(🌹)