扫雷游戏思路及代码分享

扫雷游戏思路及代码分享

今天和大家分享一下扫雷游戏,这个与上次分享的三子棋游戏差不多。
一、首先建立工程,然后添加三个文件,一个头文件(game.h),两个源文件(game.c和test.c),game.c主要用于一些函数实现,test.c主要是用于大致的框架,game.h用于一些函数声明和一些头文件的包含。
二、游戏实现

(一)先打印出一个菜单出来,就如同下面一样
在这里插入图片描述
然后我们根据输入的数字来决定后续的进行,如果你输入1则开始游戏部分,输入0则退出游戏,如果输成其他数字则打印出“选择错误,请重新输入”的一句话。大家如果看了我上次写的三子棋的博客应该就可以知道接下来我们还是要利用switch()语句,以及一个menu()来打印出上面的菜单出来。由此,代码如下:
menu()部分代码

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("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新输入!\n");
			break;
		}
	} while (input);
}

(二)接下来就game()内部的实现了

  1. 创建棋盘数组,这次我们需要创建两个数组,一个数组用来存放布置好雷的信息(mine[ROWS][COLS]),另一个数组用来存放排查出的雷的信息(show[ROWS][COLS])。(在这里插几句话,为了保证数组不越界,在数组范围上我们对它进行了变化,虽然我们只打印9*9的,但是在排雷过程中,要求对该坐标下周围的八个位置的进行排查,所以在创建数组时进行了变化
#define ROW 9
#define COL 9

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

现在我们需要确定是创建字符数组还是整形数组,为了让打印出下面的棋盘,我们创建字符数组
在这里插入图片描述
2.创建完字符数组后,要想打印出这个棋盘,我们还有一些步骤需要进行,先对两个数组进行初始化,对mine数组所有的元素初始化为‘0’,对show数组所有的元素初始化为‘*’,因为我们对这两个数组的初始化的值不同且为了避免不必要的代码重复,我们跟上次三子棋初始化的函数有所不同,将初始化的值作为一个变量set放入函数中,这样就减少了代码重复。先对函数进行声明
代码如下:

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);

接下来就是初始化函数代码的实现,代码如下:

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

而这两个数组的初始化函数的使用如下:

InitBoard(mine , ROWS , COLS , ‘0’ );
InitBoard(show , ROWS , COLS , ‘*’ );

3.初始化后,我们进行一下打印棋盘看看
依旧是打印函数声明:

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

为了棋盘之间的分隔,随便在上下打印一行分割线

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	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 ", board[i][j]);
		}
		printf("\n");
	}
	printf("---------扫雷游戏----------\n");
}

先打印一下这两个棋盘(待会在进行游戏前把mine函数打印行注释掉)

//打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);

在这里插入图片描述
4.然后就是布置雷了
声明一个SetMine函数对雷进行布置

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col, int count);

为了保证每次游戏的雷的位置不同,采用随机数的方法布置,代码如下:

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col, int count)
{
    
    
	while (count)
	{
    
    
		//1-9
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
    
    
			//x,y坐标处没有雷
			mine[x][y] = '1';
			count--;
		}
	}
}

当然要在主函数之前设置一下随机起点,依旧像上次一样使用时间戳的形式(当然要注意引用一下头文件以及强制类型转换 unsigned int):

srand((unsigned int)time(NULL));

5.雷已经布置好了,接下来就是进行排查雷
先进行函数声明:

//排查雷
void FineMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

通过输入坐标,之后对坐标进行判断是否合法以及判断该坐标处是不是雷?不是雷,统计周围雷的个数
代码如下:

//排查雷
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    
    
	int win = 0;
	//9*9-10=71
	while (win<row*col-EASY_COUNT)
	{
    
    
		printf("请输入要排查的坐标:>");
		int x = 0;
		int y = 0;
		scanf("%d%d", &x, &y);
		//1.坐标合法性
		if (x >= 1 && x <= row&&y >= 1 && y <= col)
		{
    
    
			if (mine[x][y] == '1')
			{
    
    
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
    
    
				//2.该坐标处是不是雷?不是雷,统计周围雷的个数
				int count = GetMineCont(mine, x, y);
				show[x][y] = count + '0';//存放的是数字字符
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入!\n");
		}
	}
	if (win == row*col - EASY_COUNT)
	{
    
    
		printf("恭喜你,排雷成功!\n");
	}
}

在判断该坐标不是雷之后,对其周围的8个坐标中统计雷的个数,由此我们声明一个函数进行统计雷的个数

//统计mine数组的x,y坐标周围的雷的个数
int GetMineCont(char mine[ROWS][COLS], int x, int y);

接下来就是函数实现了:

//统计mine数组的x,y周围的雷的个数
int GetMineCont(char mine[ROWS][COLS], int x, int y)
{
    
    
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		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';
}

值得注意的是在返回值的时候,因为我们定义的是字符数组所以在加的时候记得减去‘0’来确保我们返回值的正确
(三)现在我们来简单地玩一下扫雷游戏
在这里插入图片描述
如果不是我自己故意找到雷,估计这个游戏还会玩得更久。这个与大家平时玩的不同,少了一些不是雷的排查之后,它的周围也不是雷的就展开,递归下去。下次再分享给大家。谢谢大家的观看。
下面是完整代码:
1.game.h

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

#define EASY_COUNT 10

#define ROW 9
#define COL 9

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

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col, int count);

//排查雷
void FineMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

//统计mine数组的x,y坐标周围的雷的个数
int GetMineCont(char mine[ROWS][COLS], int x, int y);

2.game.c

#include "game.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;
		}
	}
}


void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	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 ", board[i][j]);
		}
		printf("\n");
	}
	printf("---------扫雷游戏----------\n");
}

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col, int count)
{
    
    
	while (count)
	{
    
    
		//1-9
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
    
    
			//x,y坐标处没有雷
			mine[x][y] = '1';
			count--;
		}
	}
}

//统计mine数组的x,y周围的雷的个数
int GetMineCont(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][y + 1] +
		mine[x - 1][y + 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] - 8 * '0';
}

//排查雷
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    
    
	int win = 0;
	//9*9-10=71
	while (win<row*col-EASY_COUNT)
	{
    
    
		printf("请输入要排查的坐标:>");
		int x = 0;
		int y = 0;
		scanf("%d%d", &x, &y);
		//1.坐标合法性
		if (x >= 1 && x <= row&&y >= 1 && y <= col)
		{
    
    
			if (mine[x][y] == '1')
			{
    
    
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
    
    
				//2.该坐标处是不是雷?不是雷,统计周围雷的个数
				int count = GetMineCont(mine, x, y);
				show[x][y] = count + '0';//存放的是数字字符
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入!\n");
		}
	}
	if (win == row*col - EASY_COUNT)
	{
    
    
		printf("恭喜你,排雷成功!\n");
	}
}

3.test.c

#include "game.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(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);

	//布置雷
	SetMine(mine, ROW, COL,EASY_COUNT);
	//DisplayBoard(mine, ROW, COL);

	//排查雷
	FineMine(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");
			break;
		}
	} while (input);
}

猜你喜欢

转载自blog.csdn.net/weixin_51548091/article/details/113108316