扫雷小游戏——简单易懂

前言

在初期版本扫雷的基础上上添加了展开,标记,防首次炸死功能;
效果展示:
在这里插入图片描述

显示与雷区设立

扫雷首先需要两个大小相等的棋盘,一个如图1用来向外界展示,一个如图2用来埋雷。

在这里插入图片描述

初始化显示棋盘和雷区棋盘

棋盘有行和列,于是乎用二维数组来进行数据统计

char board[ROW][LINE];
	memset(board, '*', sizeof(board));//显示的没点开之前为*
	char mineboard[ROW][LINE];
	memset(mineboard, '0', sizeof(board));//雷的统计初始化为0
	Mineset(mineboard);//设置雷区

棋盘显示函数

将显示棋盘进行初始化为 * 后,用显示函数将其显示出来;

static void Showboard(char board[][LINE], int row, int line) //棋盘显示
{
	printf("    ");
	for (int i = 0; i <row-2; i++)
	{
		printf(" %2d |", i+1);
	}
	printf("\n------------------------------------------------------\n");
	for (int i = 1; i < row - 1; i++)
	{
		printf(" %2d|", i);
		for (int j = 1; j < line - 1; j++)
		{
			printf(" %2c |", board[i][j]);
		}
		printf("\n------------------------------------------------------\n");
	}
}

显示效果图如下

在这里插入图片描述

雷区的设立

很显然,雷区棋盘需与显示棋盘同等大小,同时在其中分布一定数目的雷,定义一个宏MINE,将其赋值给count,每成功设立一颗雷,count就减一,设定的宏的大小就是雷的数目;

static void Mineset(char mineboard[][LINE])//随机分布雷
{
	int x = 0;
	int y = 0;
	int count = MINE;
	while (count)
	{
		x = (rand() % (ROW - 2)) + 1;
		y = (rand() % (LINE - 2)) + 1;
		if (mineboard[x][y] == '0')
		{
			mineboard[x][y] = '1';
			count--;
		}
	}
}

扫雷统计功能

上面提到两个棋盘,但是是独立分开的,那么是怎么联系在一起的呢?这个统计功能就是将两个棋盘联系在一起,当输入扫雷坐标后,通过雷区棋盘判定是否有雷,再将这个信息赋值给显示棋盘;

static char Detect(char mineboard[][LINE], int x, int y)//进行扫雷时,如果不是雷,则显示周围雷数
{
	if (mineboard[x][y] == '0')
	{
		return mineboard[x][y - 1] + mineboard[x][y + 1] \
			+ mineboard[x - 1][y - 1] + mineboard[x - 1][y] \
			+ mineboard[x - 1][y + 1] + mineboard[x + 1][y - 1]\
			+ mineboard[x + 1][y] + mineboard[x + 1][y + 1]-7*'0';
	}
	if (mineboard[x][y] =='1')
	{
		return OVER;
	}
}

防第一次炸死功能

设定一个函数,当我们进行第一次输入坐标的时候,如果判定是雷,就将这颗雷挪走,再随机设置一颗雷;

static void Firstmine(char mineboard[][LINE], int x, int y)//避免第一次被炸死
{
	if (mineboard[x][y] == '1')
	{
		mineboard[x][y] = '0';
	}
	while (1)
	{
		x = (rand() % (ROW - 2)) + 1;
		y = (rand() % (LINE - 2)) + 1;
		if (mineboard[x][y] == '0')
		{
			mineboard[x][y] = '1';
			break;
		}
	}
}

平铺函数

如下图,黑色是坐标点,该函数统计的是分别以黄色为中心点统计其周围雷的数目;
在这里插入图片描述

static void Openmine(char board[][LINE], char mineboard[][LINE], int x, int y)//平铺展开函数
{
		board[x][y - 1] = Detect(mineboard,x,y-1);
		board[x][y + 1] = Detect(mineboard, x, y + 1);
		board[x - 1][y - 1] = Detect(mineboard, x-1, y - 1);		
		board[x - 1][y] = Detect(mineboard, x-1, y );	
		board[x - 1][y + 1] = Detect(mineboard, x-1, y + 1);	
		board[x + 1][y - 1] = Detect(mineboard, x+1, y - 1);		
		board[x + 1][y] = Detect(mineboard, x+1, y );			
		board[x + 1][y + 1] = Detect(mineboard, x + 1, y + 1);
}

标记功能

标记功能是每进行一次输入就提示一次是否需要进行标记,标记的地方会显示为‘#’,如图所示
在这里插入图片描述

static void Lable(char board[][LINE])//标记坐标
{
	int x = 0;
	int y = 0;
	int quit = 0;
	int select = 0;
	while (!quit)
	{
		printf("请输入是否需要进行标记#1.yes#2.no\n");
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			printf("请输入你的标记坐标\n");
			scanf("%d %d", &x, &y);
			board[x][y] = '#';
			system("cls");
			Showboard(board, ROW, LINE);
			break;
		case 2:
			quit = 1;
			break;
		default:
			printf("输入有误,请从新输入\n");
		}
	}

}

判断胜负统计

通过统计显示棋盘剩余的空白处和标记数与设定的雷区数目进行比较,如果想等则玩家胜利;

static int Blank(char board[][LINE], int row, int line)//判断棋盘剩余的空白处
{
	int count = 0;
	for (int i = 1; i < row - 1; i++)
	{
		for (int j = 1; j < line - 1; j++)
		{
			if (board[i][j] == '*' || board[i][j] == '#')
			{
				count++;
			}
		}
	}
	return count;
}

主体函数逻辑

将上述函数进行整体连接;

void Game()
{
	srand((unsigned)time(NULL));
	char board[ROW][LINE];
	memset(board, '*', sizeof(board));//显示的没点开之前为*
	char mineboard[ROW][LINE];
	memset(mineboard, '0', sizeof(board));//雷的统计初始化为0
	Mineset(mineboard);//设置雷区
	int n = 1;//防炸死次数;
	while (1) //
	{
		system("cls");
		Showboard(board, ROW, LINE);//展示棋盘
		while (1)//判断是否需要进行标记;
		{
			Lable(board);
			break;
		}
		int quit = 0;
		int x = 0;
		int y = 0;
		while (!quit)//循环输入坐标扫雷
		{
			printf("请输入你的坐标\n");
			scanf("%d %d", &x, &y);
			if (x<0 || x>ROW - 2 || y<0 || y>LINE - 2)
			{
				printf("输入越界,请从新输入\n");
				continue;
			}
			if (board[x][y] != '*' && board[x][y] != '#')
			{
				printf("此处已经排除,请从新输入\n");
				continue;
			}
			quit = 1;
		}
		while (n)//排除第一次被炸死
		{
			Firstmine(mineboard, x, y);
			n--;
			break;
		}
		int result = Detect(mineboard, x, y);//判断是否被炸死
		if (result == OVER)//炸死了
		{
			system("cls");
			board[x][y] = OVER;
			Showboard(board, ROW, LINE);
			printf("很遗憾,你被炸死了\n");
			printf("雷区分布如下\n");
			Showboard(mineboard, ROW, LINE);
			break;
		}
		else//没炸死
		{
			if (result == '0')//如果该扫雷处周围8个都是安全的,就将周围8个的周围8个的雷数显示出来;
			{
				Openmine(board, mineboard, x, y);
			}
			board[x][y] = result;
		}
		int Win = Blank(board, ROW, LINE);
		if (Win == MINE)
		{
			printf("恭喜你,你赢了\n");
			break;
		}
	}
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值