随机迷宫生成与寻路算法(1)深度优先搜索

本文介绍了使用深度优先搜索(DFS)算法生成随机迷宫的方法。首先,通过二维数组表示迷宫,利用布尔值区分障碍和通道。接着,详细阐述了DFS算法的递归回溯过程,包括如何标记通路、判断相邻方块的合法性以及恢复路径。最后,展示了代码实现和生成的迷宫效果,并提出通过随机选择方向增加随机性的改进。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

迷宫生成算法(1)深度优先搜索

接下来一段时间,想要研究下随机迷宫生成算法,打算在有空可时候偶尔更新一下这方面的学习过程。随机迷宫的生成算法有很多种,比如递归回溯,递归分割,随机Prime等等。今天是第一次尝试随机迷宫生成,就先试一下用递归的方法通过深度优先搜索来生成随机迷宫。

首先我们来明确一下基本观念,迷宫可以通过一个二维数组来表示,二维数组中的元素就表示存在于迷宫中的位置,他们可能是可以行走的路,也有可能是不能进入的障碍物或者围栏。我们只要通过两种不同的字符就可以标记障碍物和通道,比如我们使用false来表示一个位置是障碍物,而使用true来表示位置可以通行。在下面的例子中我们就沿用这个规定,整个迷宫可以使用一个二维的布尔型数组来表示。

接下来我们确定一下对迷宫的看法,我们认为一个迷宫只能有唯一解,也就是说从起点到终点不会有两条不一样的路线。而遍历迷宫的过程可以被看成是一个拆墙的过程,如果拆了一个墙会导致两个已经被标记为通道的方块连接,那么拆这面墙就是不合法的,这个条件是递归回溯过程中最重要的判定条件。

最后来看一下递归回溯算法的过程:

  1. 将初始位置设置为当前位置(入栈),然后将它标记为通路
  2. 从上,下,左,右四个方向寻找当前方块的相邻方块,判断找到的相邻方块周围是否有其他通路,如果有则继续寻找其他相邻方块,如果没有则选择该方块为当前方块(入栈)
  3. 标记当前方块为通路,然后重复进行上一个过程
  4. 如果当前方块的相邻方块都不满足条件,则恢复上一个方块为当前方块(出栈),并继续执行过程2

以上就是深度优先遍历生成随机迷宫的基本步骤,接下来我们看代码实现:

定义一个迷宫类,它的私有数据成员保存着记录迷宫状态的二维数组,查找方向,迷宫尺寸,入口点等信息:

class Maze
{
   
public:
    //构造函数,通过传入的参数创建并创建并初始化二维数组
	Maze(int row, int column);
	ostream& print();
	//设置迷宫入口的内联函数,注意这个入口并不是遍历起点,而是在边界上挖出的一个洞
	void setEntry(int x,int y)
	{
   

		if (isValidEntry(x,y)) {
   
			mazePtr[x - 1][y - 1] = true;
			if (x == 1) {
   
				startX = 2;
				startY = y;
			}
			if (x == row) {
   
				startX = row-1;
				startY = y;
			}
			if (y == 1) {
   
				startX = x;
				startY = 2;
			}
			if (y == column) {
   
				startX = 2;
				startY = column-1;
			}
			//cout << mazePtr[x - 1][y - 1];
		}
	}
    //创建迷宫
	bool createMaze();
private:
	bool isInRange(int x, int y);
	bool isValidEntry(int x, int y);
    //递归回溯的算法的核心实现
	bool dig(int x, int y);
	int startX;
	int startY;
	int row;
	int column;
	vector<pair<int,int>> direction = {
    {
   1,0},{
   0,1},{
   -1,0},{
   0,-1} };
	unique_ptr<bool*[]> mazePtr;
};

然后我们在类外完成对构造函数的定义,他接受行列两个参数来动态创建一个布尔型二维数组,并与此同时初始化为false,允许通过初始化列表来为动态分配的内存初始化是C++11引入的新特性,这里为了方便管理堆内存,采用了智能指针类型unique_ptr来管理动态分配的内存,这种智能指针类型也是C++11新增的:

Maze::Maze(int row, int column):row(row),column(column)
{
   
	mazePtr.reset(new bool*[row]);
	for (int i = 0; i < row
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值