探索经典游戏:扫雷小游戏

C/C++
154
0
0
2024-04-12

上一次我们制作了三子棋小游戏,这一次也要稍微加大一点难度,来完成扫雷小游戏(三子棋链接:三子棋小游戏(可改棋盘大小)_总之就是非常唔姆的博客-CSDN博客)

扫雷游戏是一款经典的单人益智游戏,旨在通过揭示方块和避开地雷来展示玩家的逻辑思维和推理能力。本文将详细介绍扫雷游戏的规则和玩法,并提供了一个用C语言编写的简单且功能较为基础的实现,让各位亲身体验做出小游戏的过程

源码部分过长,不占用文章篇幅,各位可移步我的gitee网址: 唔姆 (Nerowlp) - Gitee.com

或者github网址:Nerosts/just-a-try: 学习c语言的过程、真 (github.com)

一、规则和玩法

扫雷游戏的目标是在一个方块网格中揭示所有非地雷方块,而不触发任何地雷。每个方块可以处于三种状态之一:未揭示、揭示和标记。未揭示的方块可以是空白方块或地雷方块,揭示的方块会显示周围的地雷数量。

如果玩家揭示了一个地雷方块,游戏结束,玩家失败。如果玩家成功揭示了所有非地雷方块,游戏胜利。

二、游戏的程序文件说明

  • game.h 中进行函数的、常数的声明,则源文件可直接include该头文件即可
  • game.c 中进行各个函数的实现:例如初始化雷区,设置地雷位置,翻开进行排雷的操作等等函数
  • body.c 即是各个函数拼接和组装的地方,和游戏总体逻辑实现的文件

所用常数一览

三、扫雷小游戏重要函数的实现

1.main() 主函数:

主函数主要是进行游戏的主体流程的控制——游戏的开始与游戏退出,用一个while的死循环来满足持续进行游戏的需求,input为0时退出游戏并退出循环,同时调用了srand()函数来为后面使用rand()函数来生成地雷坐标进行准备。

int main()//主函数主要是进行游戏的主体流程的控制——游戏的开始与游戏退出,用一个while的死循环来满足持续进行游戏的需求,input为0时退出游戏并退出循环
{
	srand((unsigned int)time(NULL));
	int input = 1;
	while (input)
	{
		menu();
		printf("请进行选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏");
			break;
		default:
			printf("输入有误,请重新输入");
			break;
		}
	}
	return 0;
}
2.menu()函数:平平常常来打印菜单
void menu()
{
	printf("***********************************\n");
	printf("***********  1. play **************\n");
	printf("***********  0. exit **************\n");
	printf("***********************************\n");
}
3.根据case 1来到game()函数:
  • intiBoard函数来进行初始化,即把mine雷数组全部初始化为0,show数组全部设为#来进行掩盖
  • setMine函数来进行雷的生成和安置
  • displayBoard函数来进行打印棋盘
  • findMine函数就是用来排雷操作的
需要注意的是:游戏虽然是9*9大小,但我们数组的大小是11*11,多了一行一列是为了后续进行统计周围8个格子里雷数量时方便。
void game()
{
	char mine[ROWS][COLS] = { 0 };//底层雷的数组
	char show[ROWS][COLS] = { 0 };//表面上展示的
	intiBoard(mine, ROWS, COLS,'0');//初始化棋盘的函数
	intiBoard(show, ROWS, COLS, '#');

	
	setMine(mine, ROW, COL);
	displayBoard(show, ROW, COL);
    
	//排除雷
	findMine(mine, show, ROW, COL);
	
}
3.1intiBoard()函数:

进行正常的赋值操作,为了泛用性多设置一个字符参数来实现对多个数组各自不同的初始化的功能

void intiBoard(char mine[ROWS][COLS], int rows, int cols,char set)//多设置一个字符参数来实现对多个数组各自不同的初始化的功能
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			mine[i][j] = set;
		}
	}
}
3.2setMine()函数:

count来进行生成雷数量的控制,rand()%9=1是为了生成1~9之间的随机数,因为游戏区域在二维数组下标为1~9的范围内

void setMine(char board[ROWS][COLS], int row, int col)
{
	int count = mineNum;
	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}
3.3displayBoard()函数:

只是利用二维数组的遍历进行打印,并附上各行各列的数字坐标

void displayBoard(char board[ROWS][COLS], int rows, int cols)
{
	printf("-------------扫雷------------\n");
	for (int i = 0; i <= ROW; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= ROW; i++)
	{
		printf("%d ", i);
		for (int j = 1; j <= COL; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------扫雷------------\n");
}

方便玩家进行坐标的输入

3.4findMine()函数:

我们 输入坐标进行游玩,排到了雷游戏直接失败了。

未排到雷会显示周围8个格子中雷的数量,我们用getMine函数来进行这个数量的计算。想要游戏胜利的话,我们要把所有的非雷部分进行排查完全,那样次数太多,所有设计了openBlank函数,帮助进行展开:要是周围没有雷,就把3*3区域全部展开。

void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y;
	int win = 0;
	while (win<row*col-mineNum)
	{
		printf("请输入排查雷的坐标:\n");
		scanf("%d %d", &x, &y);
		
			if (mine[x][y] == '1')
			{
				printf("很遗憾,排到了雷,被炸了。雷的位置如下(数字1代表雷)\n");
				displayBoard(mine,ROW, COL);
				break;
			}
			else
			{
				int c = getMine(mine, x, y);
				show[x][y] = (char)c;
				openBlank(mine,show, x, y);
				displayBoard(show, ROW, COL);
				win++;
			}
	}
	if (win == row * col - mineNum)
	{
		printf("恭喜你,赢了");
		displayBoard(mine, ROW, COL);
	}
}
4.getMine()函数:

因为就8个格子我们可以直接进行计算

int getMine(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] +
		mine[x - 1][y] + mine[x][y] + mine[x + 1][y] +
		mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0';
}

5.openBlank()函数:

利用遍历进行:“展开”

void openBlank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (mine[x][y] == '0')
	{
		for (int i = x - 1; i <= x + 1; i++)
		{
			for (int j = y - 1; j <= y + 1; j++)
			{
				show[i][j] = ' ';
				
			}
		}
		mine[x][y] = ' ';
	}
}

效果如图所示

四.总结

在这个扫雷游戏的实现中,我们使用了多个函数来完成不同的功能。我们首先初始化游戏板,然后随机放置地雷,并计算每个方块周围的地雷数量。接下来,我们可以通过揭示方块或标记方块来进行游戏操作。我们还实现了判断游戏是否结束以及是否胜利的函数,并在游戏结束时打印游戏板。

与上次的三子棋小游戏相比,这个扫雷游戏的实现更加复杂。它涉及到更多的逻辑和功能,例如地雷的放置和计算周围地雷数量。同时,扫雷游戏的游戏板也更加复杂,包含了多个方块和方块的不同状态。

然而,这两个游戏都有一些共同之处。它们都使用了函数来完成不同的功能,并且都需要判断游戏是否结束以及是否胜利。此外,它们都可以通过打印游戏板来显示游戏的状态。

总的来说,这两个游戏都是基于逻辑和判断的小游戏,通过实现不同的功能函数,可以完成游戏的各个操作,并进行游戏的判断和打印。这些小游戏的实现可以帮助我们更好地理解和练习编程的基本概念和技巧。

最后感谢各位的支持!!!