详解C语言小游戏——扫雷

游戏分析

在写游戏之前,然后可以先去看一下扫雷的具体图面以及具体功能然后进行分析

只是一个简单的扫雷界面,可以看出,该界面是由9*9组成的,所以我们在创建的时候,可以通过创建一个二维数组来实现这一界面。

当我们点进去之后,就会显示该位置是不是雷,不是雷的话就统计周围有几个雷,然后显示在屏幕我们点的位置上(本上图是因为在网上找的,点进去之后如果不是雷并且周围没有雷就会显示一篇,只是通过函数递归实现的,具体后面我会详细介绍)

每一个雷都是放在这个界面的某个位置,也就是通过对一个二维数组布置雷的。

在设布雷的时候,我们可以通过对雷和不是雷用不同的符号区分,你可以用’*‘表示雷’#‘表示非雷或者其他的符号,而我这边采用'1'表示雷,'0'表示非雷,这样子可以方便计算周围雷的个数(若是不懂可以先看下去,下面有代码以及画图解释)。

我们可以创建两个二维数组,一个用来布置雷,一个用来给用户显示信息。

 

在排查雷的时候,我们是要对周围的8个坐标继续统计,但是当排查的坐标位于边缘的时候,我们统计的坐标就会造成越界操作,所以当我们创建的时候可以创建11*11的坐标,这样子只需要对该边缘坐标继续初始化,当9*9的统计周围雷的信息的时候就不会造成越界访问了。

对于这种代码偏多的小游戏,我们采用模块化方式继续编写代码。

以上就是游戏内容的分析,下面就会从代码方面进行分析。

代码分析

main函数中

和三子棋类似,我们采用do.....while();循环继续。

首先我们得打印一个简单的菜单栏,和用switch分支语句进行选择判断。

 

 然后进行游戏代码部分讲解

游戏部分

与三子棋类似,我们把行和列都用宏了定义,这样子当要修改时就方便了很多。

game函数中,实现的模块也跟三子棋类似,先对二维数组进行初始话,这里创建二维数组的时候把二维数组定义为char型,是因为char型和int型之间,也就是字符'0'和数字之间是可以相互转换的,只需要把数字加上字符'0'就可以得出该数字对应的字符。

二维数组初始化

void Initboard(char board[ROWS][COLS], int row, int col, char ch)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ch;
		}
	}
}

本代码需要特别注意的是初始化的形式,因为创建的两个二维数组初始化值是不同的,布置雷的数组要初始化为'0',而显示屏幕的数组要初始化为'*',所以把要初始化的内容也传进去,这样子就可以实现一个函数可以初始化多个不同类型的符号了。

打印棋盘

void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("************扫雷*************\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

打印棋盘的时候,顺便把各个坐标的行号和列号打印上去,方便玩家输入坐标。

布置雷

 

void Setmine(char board[ROWS][COLS], int row, int col)
{
	//布置10个雷
	//雷的坐标随机产生
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;//产生1-9的数
		int y = rand() % col + 1;//产生1-9的数
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
} 

布置雷的时候,我们需要让电脑随机生成坐标然后进行随机布置,这就需要用到库函数中的rand函数,而使用rand一定要先定义srand函数,只是该函数硬性要求。

要产生1-9这个范围之间的数,可以用%这个操作符进行操作。

排查雷

看代码里面注释

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_s("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)//检查坐标合法性
		{
			if (mine[x][y] == '1')//表示该坐标本就是雷
			{
				printf("很遗憾,你被炸死了\n");
				Displayboard(mine, ROW, COL);//游戏结束把布置雷的界面打印出来,让玩家死得瞑目
				break;
			}
			else
			{	//该位置不是雷,就统计周围有几个雷
				int count = GetMineCount(mine, x, y);//通过函数进行统计
				show[x][y] = count + '0';//count+'0'=count对应的字符数字
				Displayboard(show, ROW, COL);
				win++;
			}
		}
		else
			printf("坐标非法,请重新输入\n");
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		Displayboard(mine, ROW, COL);
	}
 }

扫雷拓展

void FindArroundmine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count = GetMineCount(mine, x, y);
	//判断是否越界
	if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
	{
		return;
	}
	//判断是否被排除
	else if (show[x][y] != '*')
	{
		return;
	}
	else if (count > 0)
	{
		show[x][y] = count + '0';
		return;
	}
	//判断是否
	else if(count == 0)
	{
		show[x][y] = ' ';
		FindArroundmine(mine, show, x, y);
		FindArroundmine(mine, show, x - 1, y);
		FindArroundmine(mine, show, x - 1, y - 1);
		FindArroundmine(mine, show, x, y - 1);
		FindArroundmine(mine, show, x + 1, y - 1);
		FindArroundmine(mine, show, x + 1, y);
		FindArroundmine(mine, show, x + 1, y + 1);
		FindArroundmine(mine, show, x, y + 1);
		FindArroundmine(mine, show, x - 1, y + 1);
	}
		
}

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("请输入坐标:>");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			else
			{
				//该位置不是雷,就统计周围有几个雷
				FindArroundmine(mine, show, x, y);

				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				for (int i = 1; i <= ROW; i++)
				{
					int j = 0;
					for (j = 1; j <= COL; j++)
					{
						if (show[i][j] == '*')
						{
							win++;
						}
					}
				}
				if (win == EASY_COUNT)
				{
					printf("恭喜你,排雷成功\n");
					Displayboard(mine, ROW, COL);
					break;
				}
				if (show[x][y] == '0')
				{
					show[x][y] = ' ';
					Displayboard(show, ROW, COL);
					Displayboard(mine, ROW, COL);

				}
				else
					Displayboard(show, ROW, COL);
			}
			
		}
		else
			printf("坐标非法,请重新输入\n");
	}
}

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值