问题描述:
以M*N的矩阵表示迷宫图,数字0代表通路,数字1代表障碍。对于走过的路径,将数字0替换为数字2,便于查看通路路径。计算机解迷宫通常用的是“穷举求解”方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回(回溯),换一个方向继续探索,直至出口位置,求得一条通路。
注:对于迷宫的矩阵,我们不必每次从cmd端输入,可在文档中以txt的形式定义保存,其相对路径为当前工程目录下,绝对路径为任意位置,但在打开该文件时,要提供该文件的详细路径名。(本程序定义的MazeMap迷宫图保存在桌面上)
#define _CRT_SECRUE_NO_WARNINGS
#include<iostream>
#include<stack>
#include<cassert>
using namespace std;
#define N 10
struct Pos
{
int _row;//矩阵行
int _col;//矩阵列
Pos(int row,int col)
:_row(row)
, _col(col)
{}
};
template<class T>
bool SearchMazePath(int* arr, int n, Pos entry, stack<T>& paths) //寻找迷宫的通路。
{
assert(arr);
paths.push(entry);
while (!paths.empty())
{
Pos cur = paths.top();
arr[cur._row*n + cur._col] = 2;//走过的路径用2标识
if (cur._row == n - 1)//到达矩阵的下边界即为找到出口
{
return true;
}
//向上探索
Pos tmp = cur;
--tmp._row;
if (arr[tmp._row*n + tmp._col] == 0)
{
paths.push(tmp);
continue;
}
//向下探索
tmp = cur;
++tmp._row;
if (arr[tmp._row*n + tmp._col] == 0)
{
paths.push(tmp);
continue;
}
//向左探索
tmp = cur;
--tmp._col;
if (arr[tmp._row*n + tmp._col] == 0)
{
paths.push(tmp);
continue;
}
//向右探索
tmp = cur;
++tmp._col;
if (arr[tmp._row*n + tmp._col] == 0)
{
paths.push(tmp);
continue;
}
paths.pop(); //若上下左右都不通,则回溯。
}
return false;
}
//读入迷宫
void GetMaze(int* arr,int n)
{
assert(arr);
FILE* fout = fopen("C:\\Users\\Administrator.T47BQSRAR0SRP03\\Desktop\\MazeMap.txt","r");//绝对路径,若为相对路径,直接输入文件名即可(在当前工程目录下)
assert(fout);//若矩阵传入失败,可直接在崩溃时捕捉拦截,快速显示其问题。防御式编程的一种
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
while (true)
{
int tmp = fgetc(fout);
if (tmp == '0' || tmp == '1')//只显示0,1,跳过了空格等其他字符
{
arr[i*n + j] = tmp - '0';
break;
}
}
}
}
}
//输出迷宫
void PrintMaze(int* arr, int n)
{
for (int i = 0; i < n;i++)
{
for (int j = 0; j < n;j++)
{
cout << arr[i*n + j] << " ";
}
cout << endl;
}
cout << endl;
}
//测试用例
void Test()
{
int arr[N][N] = {};//N由宏预编译阶段替换
Pos sp(2, 0);//入口坐标
GetMaze((int*)arr, N);
PrintMaze((int*)arr, N);
stack<Pos> paths;//创建路径栈
SearchMazePath((int*)arr, N, sp, paths);//二维数组实际存储是一维数组,所以强制转换成一维用于传参。
PrintMaze((int*)arr, N);
}
int main()
{
Test();
return 0;
}
注:对于当前位置为“死路”时,需要进行回溯,退回到最近一次可走的位置点,但是每一次的回退依然存在上下左右的判断,性能上依旧可以优化,可以借助递归的方式简化回退的重复探索问题,并且对于存在多条通路路径时,还存在最优的路径问题,即最短路径的判断,所以说该程序只是迷宫问题的基础实现。。