扫雷(第一次不能炸死及展开)

C语言小程序————扫雷

学习了一段时间的C语言,写一个扫雷小游戏练习一下!
大概思路是这样的:1.打印地图,2.埋雷,3,排雷,4.判断游戏结果。
首先打印地图:在这里用一个二维数组来表示我们的地图,在这里我们创建两个二维数组,一个11 * 11用于埋雷和排雷,只有在游戏结束后才对玩家显示该数组,一个9 * 9用于向玩家展示每一步操作后的结果,.为什么要创建这样的两个数组呢?这和扫雷的游戏规则有关,游戏规则:玩家任意点开一个方框,若不是雷 ,则在这个方框上显示周围8个格子类雷的个数总和。
在这里插入图片描述
假如玩家点开标号为1的这个方格,我们就要统计其周围8个格子里面的雷的个数。这必然会遇到数组越界的问题 ,因此我们创建一个1111的数组用于埋雷和排雷,这显然就巧妙的解决了这个问题。然后将显示展示在99的数组上。
打印地图的代码如下:首先初始化这两个数组,第一个用字符0初始化,第二个用*号初始化。

#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9

void init_arr(char mine[ROWS][COLS], char show[ROW][COL])
{
	memset(mine, '0', ROWS*COLS);
	memset(show, '*', ROW*COL);
}

然后,打印地图:

void display_mine(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= y; i++)
	{
		printf("%d ", i );
		for (j = 1; j <= y; j++)
		{
			printf("%c ", mine[i][j]);
		}
		printf("\n");
	}
}


void display_show(char show[ROW][COL], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 0; i < x; i++)
	{
		printf("%d ", i + 1);
		for (j = 0; j < y; j++)
		{
			printf("%c ", show[i][j]);
		}
		printf("\n");
	}
}

第二步就是埋雷了:在这里我们采用随机数的方式进行埋雷,代码如下:

void set_mine(char mine[ROWS][COLS], int x, int y)
{
	int count = Count;
	int i = 0;
	int j = 0;
	while (count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		//printf("(%d,%d)\n", x, y);
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

我们总共埋10个雷,x,y的取值范围为1–9,我们在第一个数组里面进行埋雷,因为起初初始化为字符0,因此只要那个位置的元素是字符0,我们就能 在此埋一个雷,同时雷数减减,循环结束则已经成功布雷。
第三步;雷埋完之后就该玩家排雷了,排雷的要求是第一次不能被炸死,而且可以实现雷区展开。代码如下

void swap_mine(char mine[ROWS][COLS], char show[ROW][COL] ,int row, int col)//排雷
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int count = 0;
	int tmp = 1;
	while (count!=row*col-Count)
	{
		printf("请输入坐标;");
		scanf("%d%d", &x, &y);
		//printf("%c\n", mine[x][y]);
		if ((x<1 || x>9) | (y<1 || y>9))
		{
			printf("坐标不合法");
			continue;
		}
		else if (mine[x][y] == '1')
		{
			if (tmp == 1)
			{
				avoid(mine, x, y);
				expand(mine, show, x, y);
				tmp++;
				//display_mine(mine, ROW, COL);
				ret = get_count(mine, x, y);
				show[x-1][y - 1] = ret + '0';
				system("cls");
				display_show(show, ROW, COL);
				count++;
			}
			else if (mine[x][y] == '1')
			{
				printf("踩雷了!\n");
				//system("cls");
				display_mine(mine, ROW, COL);
				return;
			}		
		}
		else if (mine[x][y] == '0')
		{
			expand(mine, show, x, y);
			tmp++;
			ret = get_count(mine, x, y);
			show[x - 1][y - 1] = ret + '0';
			//open_mine(mine, show, x-1 , y-1);
			system("cls");
			display_show(show, ROW, COL);
			count++;
		}
	}
	printf("恭喜你,你赢了\n");
	//system("cls");
	display_mine(mine, ROW, COL);
}

怎样排雷呢?首先玩家输入坐标,判断玩家输入的坐标是否合法,不合法提醒玩家重新输入,坐标合法后,判断是不是第一次输入,且判断是不是第一次就遇到雷,如果是雷的话我们就调用移雷函数,将这个雷移去其他地方 ,如果不是游戏继续,然后呢对玩家每次输入的坐标进行判断,如果是雷,则告诉玩家踩雷了,打印雷数组游戏结束,如果地图上所剩的方格中*号的数目等于雷的数目的话则说明,排雷结束,打印雷数组玩家胜利。
移雷函数代码:

void avoid(char mine[ROWS][COLS], int x, int y)//防止第一次被炸死
{
	if (mine[x][y] == '1')
	{
		mine[x][y] = '0';
		while (1)
		{
			int x1 = rand() % 9 + 1;
			int y1 = rand() % 9 + 1;
			if (mine[x1][y1] == '0' && ((x1 != x ) && (y1 != y)))
			{
				mine[x1][y1] = '1';
				break;
			}
		}
	}
}

统计雷 的数目的函数代码:

int get_count(char mine[ROWS][COLS],int x,int y)//获取周围雷的数目
{
	int ret = 0;
	ret = (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]) - 48 * 8;
	return ret;
}

递归实现雷区展开的函数代码:

void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//雷区展开
{
	if ((x >= 1) && (y >= 1) && (x <= ROW) && (y <= COL))
	{
		if (get_count(mine, x, y) == 0)
		{
			show[x][y] =' ';
			if (show[x - 1][y - 1] == '*')
			{
				expand(mine, show, x - 1, y - 1);
			}
			if (show[x - 1][y] == '*')
			{
				expand(mine, show, x - 1, y);
			}
			if (show[x - 1][y + 1] == '*')
			{
				expand(mine, show, x - 1, y + 1);
			}
			if (show[x][y + 1] == '*')
			{
				expand(mine, show, x, y + 1);
			}
			if (show[x + 1][y + 1] == '*')
			{
				expand(mine, show, x + 1, y + 1);
			}
			if (show[x + 1][y] == '*')
			{
				expand(mine, show, x + 1, y);
			}
			if (show[x + 1][y - 1] == '*')
			{
				expand(mine, show, x + 1, y - 1);
			}
			if (show[x][y - 1] == '*')
			{
				expand(mine, show, x, y - 1);
			}

		}
	}
}

完整游戏代码:
game.h

#define _CRT_SECURE_NO_WARNINGS 2
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
#define Count 10
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
void menu();
void init_arr(char mine[ROWS][COLS],char show[ROW][COL]);//数组初始化
void display_show(char show[ROW][COL],int x,int y);//地图打印
void display_mine(char mine[ROWS][COLS], int x, int y);//地图打印
void set_mine(char mine[ROWS][COLS], int x, int y);//埋雷
void swap_mine(char mine[ROWS][COLS],char show[ROW][COL], int row, int col);//排雷
int get_count(char  mine[ROWS][COLS],int x,int y);//统计周围累的数目
void avoid(char mine[ROWS][COLS], int x, int y);//防止第一次被炸死
void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//雷区展开

game.c

#include"game.h"
void menu()
{
	printf("******************************\n");
	printf("**********1. P L A Y**********\n");
	printf("**********0. E X I T**********\n");
	printf("******************************\n");
}
void init_arr(char mine[ROWS][COLS], char show[ROW][COL])
{
	memset(mine, '0', ROWS*COLS);
	memset(show, '*', ROW*COL);
}
void display_show(char show[ROW][COL], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 0; i < x; i++)
	{
		printf("%d ", i + 1);
		for (j = 0; j < y; j++)
		{
			printf("%c ", show[i][j]);
		}
		printf("\n");
	}
}
void display_mine(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= y; i++)
	{
		printf("%d ", i );
		for (j = 1; j <= y; j++)
		{
			printf("%c ", mine[i][j]);
		}
		printf("\n");
	}
}
void set_mine(char mine[ROWS][COLS], int x, int y)
{
	int count = Count;
	int i = 0;
	int j = 0;
	while (count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		//printf("(%d,%d)\n", x, y);
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
void swap_mine(char mine[ROWS][COLS], char show[ROW][COL] ,int row, int col)//排雷
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int count = 0;
	int tmp = 1;
	while (count!=row*col-Count)
	{
		printf("请输入坐标;");
		scanf("%d%d", &x, &y);
		//printf("%c\n", mine[x][y]);
		if ((x<1 || x>9) | (y<1 || y>9))
		{
			printf("坐标不合法");
			continue;
		}
		else if (mine[x][y] == '1')
		{
			if (tmp == 1)
			{
				avoid(mine, x, y);
				expand(mine, show, x, y);
				tmp++;
				//display_mine(mine, ROW, COL);
				ret = get_count(mine, x, y);
				show[x-1][y - 1] = ret + '0';
				system("cls");
				display_show(show, ROW, COL);
				count++;
			}
			else if (mine[x][y] == '1')
			{
				printf("踩雷了!\n");
				//system("cls");
				display_mine(mine, ROW, COL);
				return;
			}		
		}
		else if (mine[x][y] == '0')
		{
			expand(mine, show, x, y);
			tmp++;
			ret = get_count(mine, x, y);
			show[x - 1][y - 1] = ret + '0';
			system("cls");
			display_show(show, ROW, COL);
			count++;
		}
	}
	printf("恭喜你,你赢了\n");
	//system("cls");
	display_mine(mine, ROW, COL);
}
int get_count(char mine[ROWS][COLS],int x,int y)//获取周围雷的数目
{
	int ret = 0;
	ret = (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]) - 48 * 8;
	return ret;
}
void avoid(char mine[ROWS][COLS], int x, int y)//防止第一次被炸死
{
	if (mine[x][y] == '1')
	{
		mine[x][y] = '0';
		while (1)
		{
			int x1 = rand() % 9 + 1;
			int y1 = rand() % 9 + 1;
			if (mine[x1][y1] == '0' && ((x1 != x ) && (y1 != y)))
			{
				mine[x1][y1] = '1';
				break;
			}
		}
	}
}
void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//雷区展开
{
	if ((x >= 1) && (y >= 1) && (x <= ROW) && (y <= COL))
	{
		if (get_count(mine, x, y) == 0)
		{
			show[x][y] =' ';
			if (show[x - 1][y - 1] == '*')
			{
				expand(mine, show, x - 1, y - 1);
			}
			if (show[x - 1][y] == '*')
			{
				expand(mine, show, x - 1, y);
			}
			if (show[x - 1][y + 1] == '*')
			{
				expand(mine, show, x - 1, y + 1);
			}
			if (show[x][y + 1] == '*')
			{
				expand(mine, show, x, y + 1);
			}
			if (show[x + 1][y + 1] == '*')
			{
				expand(mine, show, x + 1, y + 1);
			}
			if (show[x + 1][y] == '*')
			{
				expand(mine, show, x + 1, y);
			}
			if (show[x + 1][y - 1] == '*')
			{
				expand(mine, show, x + 1, y - 1);
			}
			if (show[x][y - 1] == '*')
			{
				expand(mine, show, x, y - 1);
			}

		}
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 2
#include"game.h"
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROW][COL] = { 0 };
	init_arr(mine, show);//***
	set_mine(mine, ROW, COL);
	//display_mine(mine, ROW, COL);
	system("cls");
	display_show(show, ROW, COL);
	swap_mine(mine,show, ROW, COL);
	
}
int main()
{
	srand((unsigned)time(NULL));
	int num = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &num);
		switch (num)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("请重新选择\n");
			break;
		}
	} while (num);

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43213517/article/details/83934271