C语言|扫雷游戏

文章目录

目录

文章目录

前言

一、建立文件

二、实现扫雷游戏的步骤

1.扫雷游戏的呈现

2.明确任务

3.代码实现

1.建立棋盘:

2. 放置雷

3.排雷,显示雷数

4.判断是否扫雷成功

四、完整代码 

总结



前言

在写完三子棋游戏代码后,我们又来学习扫雷游戏的代码。

一、建立文件

C语言|扫雷游戏_第1张图片

 依旧是建立三个文件。扫雷.h放各种函数声明,宏定义的。test.c文件放的是扫雷游戏的测试逻辑,呈现给玩家看的。扫雷.c放的是实现游戏的函数和各种程序。

二、实现扫雷游戏的步骤

1.扫雷游戏的呈现

                                             C语言|扫雷游戏_第2张图片

 这是我在浏览器网页上找的一个在线可玩的扫雷游戏。我们今天就是来做一个简陋的扫雷。

从这张图上,我们可以看出来,我们首先要做的就是建立棋盘。我们且叫它棋盘吧。

然后,我们随便点一个区域,会出现这种情况。

                                             C语言|扫雷游戏_第3张图片

从中,我们可以看出来,我们要实现的东西,还有随机把雷放在棋盘中,然后判断我们所选的地方有没有雷,四周有没有雷,然后要显示周围雷数。最后,我们还要判断是否排雷成功。

                                           C语言|扫雷游戏_第4张图片


2.明确任务

1.建立棋盘

2.放雷

3.排雷,显示雷数(这边还会用到递归的知识)

4.判断是否成功扫雷

3.代码实现

1.建立棋盘:

首先,我们要设置两个数组,一个数组用来存放放置好的雷的信息,另一个数组用来存放排查处理的雷的信息,设置两个数组就可以避免干扰。

其次,我们要判断周围八个坐标有没有雷,要显示周围雷的个数。那我们是不是要考虑一下边缘部分呢?边缘部分要判断的话,就要越界访问了,不就出错了吗?

                                          C语言|扫雷游戏_第5张图片

像这样,我们建立一个多设两行,多设两列,然后在里面不放东西,就好了,也省去了判断是否在边缘位置,给我们省下了麻烦。

还是先在扫雷.h中先宏定义,行列数,实际行列数,放雷个数。

#define Row  9
#define Col  9
#define Rows Row + 2
#define Cols Col + 2
#define minecount 10

 在game.c中,我们初定义二维数组,建立棋盘:

void Init_board(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;
		}
	}
}

//打印行线
void line_board(int row, int col)
{
	int i = 0;
	for (i = 0; i <= row; i++)
	{
		printf("----");
	}
	printf("\n");
}
void Print_board(char board[ROWS][COLS], int row, int col)
{
	int n = 0;
	for (n = 1; n <= col; n++)
	{
		printf(" %-3d", n);
	}
	printf("\n");
	line_board(row, col);
	int i = 0;
	for (i = 1; i <= row; i++)
	{
		printf("%-3d|", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf(" %c |", board[i][j]);
		}
		printf("\n");
		line_board(row, col);
	}

2. 放置雷

我们要避免在一个格子里,放两个雷。

void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = minecount;
	while (count)
	{
		//利用rand函数随机生成在棋盘上的雷
		x = rand() % row + 1;
		y = rand() % col + 1;
		//if语句避免重复放雷
		//1:有雷;0:无雷
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

3.排雷,显示雷数

①获取输入坐标周围雷的数量

static int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	//这就是为什么我们把真实棋盘初始化为0,有雷设1的原因了。这样子程序更简单
	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';
}

                              C语言|扫雷游戏_第6张图片

② 递归展开一片区域

要满足以下三个条件,可以递归去看周围的8个坐标:

1.该坐标不是雷

2.该坐标没有被排查过

3.该坐标周围没雷

void Unfold(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y, int* win)
{
	if (x >= 1 && x <= row && y >= 1 && y <= col)//在棋盘内
	{
		if (show[x][y] == ' ' || show[x][y] != '*')//该坐标已被排查过,或不是雷
			return;
		else if (get_mine_count(mine, x, y) != 0)//该坐标周围没有雷
		{
			show[x][y] = get_mine_count(mine, x, y) + '0';
			(*win)++;
			return;
		}
		else
		{
			show[x][y] = ' ';
			(*win)++;
			Unfold(mine, show, row, col, x - 1, y, win);
			Unfold(mine, show, row, col, x + 1, y, win);
			Unfold(mine, show, col, col, x, y - 1, win);
			Unfold(mine, show, row, col, x, y + 1, win);

		}
	}
	return;
}

4.判断是否扫雷成功

void Find_mine(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) - minecount)
	//row*col的结果是一整个可见棋盘的大小个数。minecount指的是埋雷个数。
	//当win等于(row*col)-minecount的值的时候,全部没有雷的区域全部排完。
	{
		printf("请输入排查雷的坐标:>\n");

		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//在棋盘内
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,您被炸死了\n");
				//被炸死后打印埋雷的棋盘
				Print_board(mine, ROW, COL);
				break;
			}
			if (show[x][y] != '*')
			{
				printf("该坐标已经被排查过了,重新输入\n");
				continue;
			}
			else
			{
				Unfold(mine, show, row, col, x, y, &win);
				Print_board(show, ROW, COL);
			}
		}
		else
		{
			printf("坐标输入错误 请重新输入\n");
		}
		if (win == (row * col) - minecount)
		{
			printf("恭喜你,扫雷成功!\n");
		}
	}
}

四、完整代码 

#include 
#include 
#include 

#define ROW 9//显示行
#define COL 9//显示列
#define ROWS ROW+2//实际行
#define COLS COL+2//实际列
#define minecount 10//放雷个数

//初始化棋盘
void Init_board(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void Print_board(char board[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);
//利用递归,展开一片
void Unfold(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y, int* win);

扫雷.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include "扫雷.h"
//初始化棋盘
void Init_board(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;
		}
	}
}

//打印行线
void line_board(int row, int col)
{
	int i = 0;
	for (i = 0; i <= row; i++)
	{
		printf("----");
	}
	printf("\n");
}
//打印棋盘
void Print_board(char board[ROWS][COLS], int row, int col)
{
	int n = 0;
	for (n = 1; n <= col; n++)
	{
		printf(" %-3d", n);
	}
	printf("\n");
	line_board(row, col);
	int i = 0;
	for (i = 1; i <= row; i++)
	{
		printf("%-3d|", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf(" %c |", board[i][j]);
		}
		printf("\n");
		line_board(row, col);
	}
}

//放置雷
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = minecount;
	while (count)
	{
		//利用rand函数随机生成在棋盘上的雷
		x = rand() % row + 1;
		y = rand() % col + 1;
		//if语句避免重复放雷
		//1:有雷;0:无雷
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

//获取输入坐标周围雷的数量
static int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	//这就是为什么我们把真实棋盘初始化为0,有雷设1的原因了。这样子程序更简单
	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 Unfold(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y, int* win)
{
	if (x >= 1 && x <= row && y >= 1 && y <= col)//在棋盘内
	{
		if (show[x][y] == ' ' || show[x][y] != '*')
			return;
		else if (get_mine_count(mine, x, y) != 0)
		{
			show[x][y] = get_mine_count(mine, x, y) + '0';
			(*win)++;
			return;
		}
		else
		{
			show[x][y] = ' ';
			(*win)++;
			Unfold(mine, show, row, col, x - 1, y, win);
			Unfold(mine, show, row, col, x + 1, y, win);
			Unfold(mine, show, col, col, x, y - 1, win);
			Unfold(mine, show, row, col, x, y + 1, win);

		}
	}
	return;
}

//查找雷
void Find_mine(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) - minecount)
	//row*col的结果是一整个可见棋盘的大小个数。minecount指的是埋雷个数。
	//当win等于(row*col)-minecount的值的时候,全部没有雷的区域全部排完。
	{
		printf("请输入排查雷的坐标:>\n");

		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,您被炸死了\n");
				//被炸死后打印埋雷的棋盘
				Print_board(mine, ROW, COL);
				break;
			}
			if (show[x][y] != '*')
			{
				printf("该坐标已经被排查过了,重新输入\n");
				continue;
			}
			else
			{
				Unfold(mine, show, row, col, x, y, &win);
				Print_board(show, ROW, COL);
			}
		}
		else
		{
			printf("坐标输入错误 请重新输入\n");
		}
		if (win == (row * col) - minecount)
		{
			printf("恭喜你,扫雷成功!\n");
		}
	}
}

test.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include "扫雷.h"
//测试扫雷逻辑
void menu()
{
	printf("请玩家输入:(1:开始游戏;0:结束游戏\n");
	printf("*********** 1 .play ************\n");
	printf("*********** 0 .exit ************\n");
}
//扫雷游戏的实现
void game()
{
	//创建存放棋盘变量
	char mine[ROWS][COLS] = { 0 };//真正的棋盘
	char show[ROWS][COLS] = { 0 };//显示给玩家看的棋盘
	//初始化棋盘
	//无雷为0,有雷为1.方便后面计算周围雷的个数
	Init_board(mine, ROWS, COLS, '0');//初始化真正棋盘
	Init_board(show, ROWS, COLS, '*');//初始化玩家看的棋盘
	//打印棋盘
	Print_board(show, ROW, COL);
	//存放雷
	set_mine(mine, ROW, COL);
	//Print_board(mine, ROW, COL);//我们测试的时候可以让他们把真正的棋盘打印出来,就可以心知肚明地做测试了。
	//排查雷
	Find_mine(mine, show, ROW, COL);

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

 

 

 


你可能感兴趣的:(游戏,算法,c语言)