C语言扫雷小游戏

475 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

为了复习C语言的语法嘛,就简单的写了一下扫雷这样一个小游戏,完全在命令行窗口运行。思路也比较简单,采用数组来模拟棋盘。一个用来模拟地雷的分布的数组。一个用来打印玩家开始看到的数组。在选择坐标后展开周围的地方。判断未展开的格子数与地雷数是否相等。结束游戏。

简单的初始界面

简单的一个初始界面,用来选择开始游戏和退出。也可以在这里在后续加上难度选择等等功能。

void ShowMenu()
{
	printf("*********************************\n");
	printf("*********************************\n");
	printf("**********输入1 开始游戏*********\n");
	printf("**********输入0 退出游戏*********\n");
	printf("*********************************\n");
	printf("*********************************\n");
	printf("\n");
	printf("\n");
	printf("\n");
	printf("               请输入:\n");

}

制作棋盘和布雷

棋盘采用二维数组来构成,为了保证游戏可以重复开始,在每次开始时都要对数组进行初始化,然后随机布“雷”。为了方便在接下来扫描展开位置周围是否有“雷”。我们将数组全部初始化为0,将“雷”标记为1。这样就可以布置好地图。

void InitMap()
{
	int count = 0;

	for (int i = 0; i <= ROW; i++)// 初始化地图
		for (int j = 0; j <= COLUMN; j++)
		{
			map[i][j] = 0;
			show_map[i][j] = '*';
		}

	while (count != BANG_NUMBER)        //埋雷
	{
		int x = rand() % ROW + 1;
		int y = rand() % COLUMN + 1;
		if (map[x][y] != 1)
		{
			map[x][y] = 1;
			++count;
		}
	}
}

void Show_BangMap()
{
	system("CLS");
	printf("*********************************\n");
	printf("*********************************\n");
	printf("\n");
	printf("   ");                  //打印 行列数
	for (int i = 1; i <= ROW; i++)
		printf(" %d ", i);
	printf("\n");
	for (int i = 1; i <= ROW; i++)  //  打印地图
	{
		printf(" %d ", i);
		for (int j = 1; j <= COLUMN; j++)
			printf(" %c ", show_map[i][j]);
		printf("\n");
	}
}

“雷”的判断与展开

在判断目标周围是否有雷时,将周围所有值相加,如果结果是0,则周围没有雷,将“ ”(空格)返回给该点。否则将“雷”数返回。 在展开时,采用递归的方式,如果改点周围没有“雷“,且周围的点还未展开时,递归展开这个位置就好。一般而言。一个数的周围会有8个位置,所以需要做8次判断。但是在边缘时,会产生数字越界的警告,因此在定义数组时,将数组的范围加大一圈。我们需要一个10x10的地图时,定义一个12x12的数组,在初始化时,将所有元素赋0。但在埋”雷“时,限制范围为10x10。

int GetBangNum(int x, int y)       //判断雷数
{
	//将周围的所有格子的数加起来来判断是否有雷
	return map[x - 1][y - 1] + map[x][y - 1] + map[x + 1][y - 1] + map[x - 1][y] + map[x + 1][y] + map[x - 1][y + 1] + map[x][y + 1] + map[x + 1][y + 1];
}

void OpenMap(int x, int y)         //判断展开
{ 
	if (GetBangNum(x,y) == 0)
	{
		show_map[x][y] = ' ';
		if (x - 1 > 0 && y - 1 > 0 && show_map[x - 1][y - 1] == '*')
			OpenMap(x - 1, y - 1);
		if (x - 1 > 0 && show_map[x - 1][y] == '*')
			OpenMap(x - 1, y);
		if (y - 1 > 0 && show_map[x][y - 1] == '*')
			OpenMap(x, y - 1);
		if (x + 1 < ROW && y + 1 < COLUMN && show_map[x + 1][y + 1] == '*')
			OpenMap(x + 1, y + 1);
		if (y + 1 < COLUMN && show_map[x][y + 1] == '*')
			OpenMap(x, y + 1);
		if (x + 1 < ROW && show_map[x + 1][y] == '*')
			OpenMap(x + 1, y);
		if (x - 1 > 0 && y + 1 < COLUMN && show_map[x - 1][y + 1] == '*')
			OpenMap(x - 1, y + 1);
		if (x + 1 < ROW && y - 1 > 0 && show_map[x + 1][y - 1])
			OpenMap(x + 1, y - 1);
	}
	else
		show_map[x][y] = GetBangNum(x, y) + 48;

判断游戏结束

判断游戏结束很简单,只需要判断在地图中的“*”是否与我们开始埋下的“雷”元素是否相等。如果相等说明目前地图中只有是“雷”的元素还没有展开,则游戏结束。

int  IsFull()   // 判断游戏是否结束
{
	int count = 0;
	for(int i =1;i<=ROW;i++)
		for (int j = 1; j <= COLUMN; j++)
			if (show_map[i][j] == '*')
				++count;
	if (count == BANG_NUMBER)
		return TRUE;
	else
		return FALSE;
}

执行游戏

接下来就没有什么问题了,将写好的函数合理调用,当键入一个坐标时,判断相应元素属性,然后按部就班调用函数。最后在用关键词switch来模拟一个游戏菜单的选择即可。

void Playing()
{
	InitMap();
	Show_BangMap();
	int x, y;
	while (TRUE)
	{
		printf("输入坐标:\n");
		scanf_s("%d%d",&x,&y);
		if (x > 0 && y > 0 && x <= ROW && y <= COLUMN)
		{
			if (map[x][y] == 1)        //踩雷
			{
				for (int i = 1; i <= ROW; i++)
					for (int j = 1; j <= COLUMN; j++)
						if (show_map[i][j] == '*')
							show_map[i][j] = '!';
				Show_BangMap();
				printf("\n");
				printf("失败!!游戏结束!!");
				break;
			}
			else                    //没有踩雷
			{
				if (GetBangNum(x, y) == 0)
					OpenMap(x, y);
				else
					show_map[x][y] = GetBangNum(x, y) + 48;
				Show_BangMap();
			}

			if (IsFull() == TRUE)     //判断胜利
			{
				for (int i = 1; i <= ROW; i++)
					for (int j = 1; j <= COLUMN; j++)
						if (show_map[i][j] == '*')
							show_map[i][j] = '!';
				void Show_BangMap();
				printf("游戏胜利!!!");
				break;
			}
		}
		else
			printf("输入有误");
	}
}
void test()
{
	ShowMenu();
	int a;
	while (TRUE)
	{
		scanf_s("%d", &a);
		switch (a)
		{
		case 1:

			Playing();
			break;
		case 2:
			printf("游戏结束!");
			return;
		default:
			printf("输入有误");
		}
	}
}