前言:
这是基于栈的迷宫问题讲解,并不是最优解,毕竟只是穷举法,所以这个算法也不可能太聪明。
迷宫问题算是很简单的算法了,所以本文无论是否了解迷宫问题都可以阅读,但是如果完全不了解STL库可能会对代码有阅读障碍。
思路讲解:
(本算法确实很简单,没啥好讲的,故而讲述会较为简略)
1.首先确定下起点和终点
2.由起点选择一个方向朝着终点出发
3.若当前方向可前行则继续选择任意一个方向前行
4.若此次前行的位置不可继续前行则记录下该坐标无法通行
5.回退到上一个位置,选择一个其它方向前行
6.继续步骤4,若三个方向都不可以继续前进,则回退到上一个位置
7.由此位置开始选择一个其它方向前进,重复上述步骤
8.直到到达终点为止
9.若起点的四个方向都不可前进了,则说明没有到达终点的路径
代码如下:
(代码注释很详细,故而不再作文字讲解,看不懂也没关系,最下方有b站的该代码的视频讲解链接)
/****************************************************
> File Name: 迷宫问题
> Author: 唯恒
> Mail: 2279811789@qq.com
> Created Time: 2022年10月23日
*******************************************************/
#include <iostream>
#include<vector>
using namespace std;
//初始化迷宫
char** const InitMaze()
{
char** const maze = new char*[12];
static char mazes[12][13]=//手动生成一个迷宫,重点在于求解迷宫问题,没必要随机生成
{
{"************"},//*代表不可走,0代表可以走
{"*0**********"},
{"*00000******"},
{"*0*0********"},
{"*0*0*0000***"},
{"***0*0**0***"},
{"***0000*0***"},
{"**00*0**0***"},
{"*****0*000**"},
{"*****0*0*00*"},
{"*****0*0**0*"},
{"************"},
};
for (int i = 0;i < 12;i++)
{
maze[i] = mazes[i];
}
return maze;
}
//行走路线图
class Path
{
public:
vector<pair<int, int>> path;//记录足迹
pair<int, int> terminus;//终点
bool Can_t_walk[12][12] ;//不能走的地方
char *maze[12];//迷宫副本
//初始化时将起点与终点入栈
Path(pair<int, int>const origin, pair<int, int>const terminus, char** maze);
//判断当前位置能否行走
bool Pass(pair<int, int>const p);
//下一步要走的位置
pair<int, int> NextDirection();
//开始寻路
void find();
};
Path::Path(pair<int, int>const origin, pair<int, int>const terminus, char** maze)
{
Can_t_walk[12][12] = { false };//不能走的地方,false可以走,true不可以走
for (int i = 0;i < 12;i++)
{
this->maze[i] = maze[i];
}
if (origin.first < 1 || origin.second < 1 || origin.first>11 || origin.second>11 ||//判断起点坐标是否非法
terminus.first < 1 || terminus.second < 1 || terminus.first>11 || terminus.second>11 ||//判断终点点坐标是否非法
origin == terminus)//如果起点==终点 毫无意义
{
perror("参数错误\n");
exit(1);
}
maze[origin.first][origin.second] = '1';//起点肯定在栈上
path.push_back(origin);//起点压栈
this->terminus = terminus;
}
bool Path::Pass(pair<int, int>const p)
{
if (maze[p.first][p.second] == '1')//不能走回头路
return false;
if (Can_t_walk[p.first][p.second] == true)//已经确定走不通的路
return false;
if (maze[p.first][p.second] == '*')//不可前进的位置
return false;
return true;
}
pair<int, int> Path::NextDirection()
{
pair<int, int>p = *--path.end();
//依次判断四个方向是否可以前进
if (Pass(make_pair(p.first + 1, p.second)))
{
return make_pair(p.first + 1, p.second);
}
else if (Pass(make_pair(p.first - 1, p.second)))
{
return make_pair(p.first - 1, p.second);
}
else if (Pass(make_pair(p.first, p.second + 1)))
{
return make_pair(p.first, p.second + 1);
}
else if (Pass(make_pair(p.first, p.second - 1)))
{
return make_pair(p.first, p.second - 1);
}
if (*path.begin() == p)//当起点找不到前行路径时说明已经找不到路了 梅梅
{ // (别问梅梅是啥意思,我后来检测代码的时候发现的,不知道按错哪两个键,就打上去了,连输入法都记到了我前女友的名字了,哭,我真的好难过,也别问我为啥不删掉这两个字,就是不想,没有为啥)
cout << "抱歉找不到正确路径" << endl;
exit(1);
}
return make_pair(-1, -1);//返回失败标志
}
void Path::find()
{
while (true)
{
pair<int, int> p = NextDirection();//获取下一次前行的位置
if (p == make_pair(-1, -1))//栈顶位置为死路弹出栈顶
{
Can_t_walk[(*(--path.end())).first][(*(--path.end())).second] = true;//标记该位置为死路
maze[(*(--path.end())).first][(*(--path.end())).second] = '0';
path.pop_back();
}
else//可以前行则压栈,并记录下当前位置已经走过
{
maze[p.first][p.second] = '1';
path.push_back(p);
}
if (*(--path.end()) == terminus)//栈顶与终点重合
{
return;
}
}
}
int main()
{
char** maze = InitMaze();
cout << "迷宫如图:" << endl;
for(int i=0;i<12;i++)
{
for (int j = 0;j < 12;j++)
{
cout << " " << maze[i][j]<<" ";
}
cout << endl << endl;
}
Path p(make_pair(1, 1), make_pair(10, 10), maze);
p.find();
cout << "路径如图:" << endl;
for (int i = 0;i < 12;i++)
{
for (int j = 0;j < 12;j++)
{
cout << " " << p.maze[i][j] << " ";
}
cout << endl << endl;
}
return 0;
}