通过深度优先搜索求解迷宫
在上一篇文章中我们实现了基于深度优先搜索(DFS)的随机迷宫生成。方法类似,我们也可以利用DFS来进行随机迷宫寻路,也就是我们这一次文章的实现目标。
我们将尝试通过深度优先搜索来求解上一篇文章中生成的随机迷宫,稍有不同的是这次我们通过栈和迭代代替上次使用的函数递归调用,这两种方法理论上来分析是等价的。
该方法很容易理解:
- 首先我们将迷宫的起始点入栈
- 将栈顶元素标记为当前坐标,然后按照已经定义好的方向数组依序从上、下、左、右四个方向(方向可以是任意的,但没必要每次都进行随机选取)来遍历当前坐标的相邻方块
- 如果这个取得的方块是合法的(也即是说这个方块不是边界,不是障碍物,并且没有标记为路线或者死胡同),则结束搜索。
- 如果这个取得的方块不合法,则进行下一个方向的搜索
- 当四个方向都搜索结束以后,判断在这个过程中是否找到了一个可行的相邻方块,如果找到了则将找到的方块入栈,然后回到步骤2
- 如果没有找到合适的相邻方块,说明当前坐标的搜索失败,此时应该将栈顶元素出栈并回到步骤2(回到上一个栈顶继续搜索),如果栈为空说明搜索回到起点,一切结束。
下面看代码,我们给上次的迷宫类添加一个新方法mazeSolve用于迷宫求解,添加一个新的stack<pair<int,int>>
变量用于保存求解路线:
bool Maze::solveMaze()
{
path.push(start);//起始点入栈
int currentX, currentY;
bool flag = false;
while (true) {
currentX = path.top().first;//记录栈顶元素为当前坐标
currentY = path.top().second;
for (int i = 0; i < 4; i++) {
//从四个方向搜索
flag = false;
currentX += direction[i].first;
currentY += direction[i].second;
if (currentX == exit.first and currentY == exit.second) {
//是否看到出口
return true;
}
if (isInRange(currentX, currentY) and (getData(currentX, currentY) > 0)) {
//如果搜索到合法相邻元素
flag = true;
path.push({
currentX, currentY });//当前坐标入栈
setData(currentX, currentY, -2);
break;
}
currentX -= direction[i].first;
currentY -= direction[i].second;
}
if (!flag) {
//若未找到合法相邻坐标
setData(currentX, currentY, -1);//标记为走错
path.pop();
if (path.empty()) {
return false;
}
}
}
}
除此以外,为了能够打印正确路线,还需要调整一下之前的print方法。新的print方法接受一个布尔类型参数,如果参数为false表示打印求解前的迷宫,如果参数为真表示打印求解后的迷宫,全部代码如下:
#include<iostream>
#include<vector>
#include<memory>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<stack>
#include<queue>
using namespace std;
pair<int, int> input()
{
cout << "please input the size of the maze:" << endl;
int row, column;
cin >> row >> column;
row = row %