扫雷-空白展开算法(优化)-详解

扫雷是电脑上很经典的游戏,虽然我没玩过。为了写这个博客,我特意去网上玩了一会。
几次调试之后,我觉得这个比三子棋要复杂一些,尤其是空白展开算法上和堵截玩家有的一拼。这个与实际游戏差别较大,不能使用光标。
接下来。我会很详细的讲解每一步分析。

写代码前,扫雷需要什么

1,游戏需要初始选择菜单
2,需要布置两个棋盘,一个布置雷,一个展示给玩家看
3,打印棋盘
4,玩家要输入选择的坐标,并且可以多次输入游戏坐标
5,每次输入后打印棋盘,同时判断是否继续还是输赢。
6,玩家每次输入坐标,都进行一次递归展开。

进行主函数文件的代码

void option(int input)
{
	switch (input)//分支语句
	{
	case 1:
		game();//扫雷开始
		break;
	case 0:
		printf("Logon out the game\n");
		break;
	default:
		printf("Input error,please input again\n");
		break;
	}
}
void menu(void)
{
	printf("Welcome to game\n");
	printf("\n");
	printf("****************\n");
	printf("*----1.play----*\n");
	printf("*----0.exit----*\n");
	printf("****************\n");
}
int main(void)
{
	
	int input;
	srand((unsigned int)time(NULL));
	do
	{
		menu();//打印游戏菜单
		printf("please input option(1/0):>");
		scanf("%d", &input);
		option(input);//选项判断
	} while (input);
	
}

game文件以及函数步骤

#include <time.h>
#define ROW 9
#define COL 9
#define _CRT_SECURE_NO_WARNINGS
#define ROWS ROW+2
#define COLS COL+2
#define LEVEL 10
#include <stdio.h>
#include <stdio.h>
void game(void);//扫雷游戏
void setboard(char board[ROWS][COLS], int rows, int cols,char ret);//初始布置棋盘内容
void showboard(char board[ROWS][COLS], int rows, int cols);//负责打印棋盘
//void player(char board[ROWS][COLS]);//玩家输入
void setmine(char mine[ROWS][COLS], int row, int col);//布置地雷
int cleanmine(char board[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
void space(char board[ROWS][COLS], char mine[ROWS][COLS], int x,int y);//空白递归算法
int test(char mine[ROWS][COLS], int x, int y);//计算周围雷数

在主函数文件中使用game函数

void game()
{
	char board[ROWS][COLS];
	char mine[ROWS][COLS];
	setboard(mine, ROWS, COLS,'0');//创建初始棋盘
	setmine(mine, ROW, COL);//布雷要在一次游戏开始时就布好雷,只布一次雷
	setboard(board, ROWS, COLS, '*');//给玩家看的棋盘
	while (1)
	{
		int ret;
		showboard(mine, ROW, COL);//打印布雷图
		
		showboard(board, ROW, COL);//打印玩家棋盘
		//player(board);
		ret=cleanmine(board,mine,ROW,COL);//扫雷
		//showboard(board, ROW, COL);
		int count = 0;//可以用一个函数进行封装
		for (int i = 1; i <= ROW; i++)
		{
			
			for (int j = 1; j <= COL; j++)
			{

				if (board[i][j] == '*')
					count++;
			}
		}
		if (count ==  LEVEL)
		{
			printf("you win\n");
			break;
		}
		if (ret == 0)
			break;
		system("cls");
		
	}
	

}

布值棋盘(雷盘和玩家棋盘)

void setboard(char board[ROWS][COLS], int rows, int cols,char ret)
{
	int i;//主要靠ret决定是布雷还是布置玩家棋盘
	for (i = 0; i < rows; i++)
	{
		int j;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ret;
		}
	}

}

打印棋盘函数

每次将棋盘重新定义后就可以打印,但是我们设置的棋盘要比打印的大两行,为了保证之后计算雷数的循环成立。

void showboard(char board[ROWS][COLS], int rows, int cols)
{
	for (int a = 0; a <= cols; a++)
		printf("%d ",a);
	printf("\n");
	int i;
	int a = 1;
	for (i = 1; i <= rows; i++)
	{
		printf("%d ", a++);
		int j;
		for (j = 1; j <= cols; j++)
		{
			printf("%c|", board[i][j]);
		}
		printf("\n");
	}
}

玩家排雷

int cleanmine(char board[ROWS][COLS],char mine[ROWS][COLS],int row,int col)
{
	int x, y;
	while (1)
	{
		printf("please input the coordinate:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '0')
			{
				board[x][y] = test(mine, x, y) + '0';
				//空白递归算法
				space(board, mine, x, y);
				//showboard(board, ROW, COL);
				break;
			}
			else if (mine[x][y] == '1')
			{
				printf("You died\n");
				return 0;
				break;
			}
		}
		else
			printf("Coordinate is illegal,please input again\n");
	}
	printf("player\n");
	//showboard(board, ROW, COL);
	return 1;
}

计算雷数的函数

int test(char mine[ROWS][COLS], int x, int y)
{
	int count = 0;
	for (int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if (mine[i][j] == '1')
				count++;
		}
	}
	return count;//count就代表返回的雷数
}

空白递归算法

void space(char board[ROWS][COLS], char mine[ROWS][COLS], int x, int y)
{
	int i;
	if(test(mine, x, y)==0)
	{
		board[x][y] = ' ';
		for (i = x-1; i <=x+1; i++)
		{
			int j;
			for (j = y-1; j <=y+1; j++)
			{
				if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1'&&board[i][j]=='*')
				{
					space(board, mine, i, j);
				}
			}
		} 
	}
	else
		board[x][y] = '0' + test(mine, x, y);
	
	
}

要使用test函数去测试某个元素周围8个元素是不是雷,如果不是,就进入函数进行递归,里面用来循环来表示各个方向的元素
在这里插入图片描述
如果检测出来test不为0,就代表周围有雷,就else玩家棋盘定义为周围雷数,同时返回上一级函数。每一次递归都有两个for循环来递归检查各个方向上的元素。
就这些,如有问题,烦请大佬指点一二

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
好的,我会尽力回答你的问题。关于扫雷游戏的布雷算法、策略与优化,其实是一个比较复杂的话题,需要涉及到一些数学、算法和编程知识。不过我会尽量用简单的语言来介绍。 首先,扫雷游戏的布雷算法是指在游戏开始前,计算机如何随机生成一个扫雷地图。一般来说,扫雷地图会被分成若干个小格子,每个格子要么是雷,要么是数字,数字代表周围八个格子中有多少个雷。布雷算法的目标就是随机分布雷和数字,让游戏变得有趣和有挑战性。 一个简单的布雷算法是随机生成若干个雷的位置,然后计算每个数字格子周围的雷数。这种算法的缺点是可能会出现非常简单或非常困难的地图,而且雷的数量可能不够平均分布。为了解决这个问题,可以采用更高级的算法,比如基于概率的布雷算法或者优化的布雷算法。 基于概率的布雷算法是指按照一定的概率分布来生成雷和数字。比如,可以先随机生成一些数字格子,然后根据周围数字格子的个数来计算生成雷的概率。这样可以保证雷的数量比较平均分布,但是仍然存在一些不合理的地图。 优化的布雷算法是指结合了各种启发式算法优化算法来生成地图,比如遗传算法、模拟退火算法、粒子群算法等。这些算法可以保证生成的地图比较合理和有挑战性,但是计算复杂度较高,需要较强的计算能力。 至于扫雷游戏的策略和优化,也有很多研究。一般来说,扫雷游戏的策略分为两种:基于推理的策略和基于直觉的策略。基于推理的策略是指根据已知的雷和数字格子,推理出未知的格子是雷还是数字。这种策略需要一定的逻辑和推理能力,可以通过编写算法自动实现。基于直觉的策略是指根据已知的局面和经验,直觉地猜测未知的格子是雷还是数字。这种策略需要一定的经验和感觉,很难通过编写算法来实现。 在实现扫雷游戏的算法时,可以使用Python这样的高级编程语言来实现。以下是一个简单的Python实现扫雷游戏的代码,供参考: ```python import random class MineSweeper: def __init__(self, width=10, height=10, mines=10): self.width = width self.height = height self.mines = mines self.grid = [[0 for y in range(height)] for x in range(width)] self.revealed = [[False for y in range(height)] for x in range(width)] self.flagged = [[False for y in range(height)] for x in range(width)] self.generate_grid() def generate_grid(self): positions = [(x, y) for x in range(self.width) for y in range(self.height)] random.shuffle(positions) mine_positions = positions[:self.mines] for x, y in mine_positions: self.grid[x][y] = -1 for dx in [-1, 0, 1]: for dy in [-1, 0, 1]: if x+dx >= 0 and x+dx < self.width and y+dy >= 0 and y+dy < self.height and self.grid[x+dx][y+dy] != -1: self.grid[x+dx][y+dy] += 1 def reveal(self, x, y): if self.grid[x][y] == -1: return False self.revealed[x][y] = True if self.grid[x][y] == 0: for dx in [-1, 0, 1]: for dy in [-1, 0, 1]: if x+dx >= 0 and x+dx < self.width and y+dy >= 0 and y+dy < self.height and not self.revealed[x+dx][y+dy]: self.reveal(x+dx, y+dy) return True def flag(self, x, y): self.flagged[x][y] = not self.flagged[x][y] def game_over(self): for x in range(self.width): for y in range(self.height): if self.grid[x][y] == -1 and self.revealed[x][y]: return True return False def game_won(self): for x in range(self.width): for y in range(self.height): if self.grid[x][y] != -1 and not self.revealed[x][y]: return False return True def print_grid(self): for y in range(self.height): for x in range(self.width): if self.revealed[x][y]: if self.grid[x][y] == -1: print("*", end="") else: print(self.grid[x][y], end="") elif self.flagged[x][y]: print("F", end="") else: print(".", end="") print() ``` 这段代码实现了一个简单的扫雷游戏,包括布雷算法、揭示格子、标记格子、游戏结束和游戏胜利的判断,以及输出游戏地图的功能。你可以根据自己的需要来调整参数和改进算法。 希望这个回答能够帮到你。如果你还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值