首先来看一下迷宫简易图
我们用 0 来表示该位置是墙, 用 1 来表示该位置是路. 所以, 我们在处理迷宫问题的时候可以将其看成一个二维数组即可, 而对应的每一条路我们可以用坐标的形式将其表示, 所以还需要有一个结构体来描述对应的点的
1. 相关数据结构
typedef struct Maze
{
int map[MAX_ROW][MAX_COL];
}Maze;
typedef struct Point
{
int row;
int col;
}Point;
2.迷宫初始化
所谓的初始化迷宫就是将这个二维数组初始化, 我们自己定义一个二维数组, 然后将其每一个值赋值给我们的迷宫地图即可
void MazeInit(Maze* maze)
{
if(maze == NULL)
{
return;
}
int Map[MAX_ROW][MAX_COL] = {
{0, 1, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 0},
{0, 0, 0, 1, 1, 0},
{0, 0, 0, 1, 0, 0}
};
int row = 0;
int col = 0;
for(; row < MAX_ROW; row++)
{
for(col = 0; col < MAX_COL; col++)
{
maze -> map[row][col] = Map[row][col];
}
}
}
3.迷宫探索
迷宫探索即就是从给出的迷宫入口开始, 一直往后探索, 直到找到出口为止. 我们利用函数在递归的过程中会形成栈桢的特性, 依次将我们所探索的为位置进行压栈, 在此过程中, 我们必须得判断当前的点是否合法, 同时必须判断当前的点是否可以落脚, 如果可以落脚, 就现将该位置标记, 然后判断当前位置是否是出口, 如果是出口, 说明迷宫探索完毕, 如果不是出口, 那么我们就得必须找下一个可以落脚的位置, 即我们依次按照顺时针的方向依次遍历当前位置四周的四个点(up, rught, down, left), 只要我们发现有一个点可以落脚, 我们就将当前位置对应的点入栈(调用函数本身), 当四个方向都已经走完了, 那么我们就得往回退, 即就是对应的出栈过程了.具体如下图
void _GetPath(Maze* maze, Point cur, Point entry)
{
if(maze == NULL)
{
return;
}
if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col > MAX_COL)
{
return;
}
if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL)
{
return;
}
printf("(%d, %d)\n", cur.row, cur.col);
//判断当前点是否可以落脚
if(CanStay(maze, cur))
//如果可以落脚, 就给当前位置标记
//如果当前点是出口, 则说明找到了一条路按顺时针方向探测四个相邻点, 递归调用函数自身,
{
Mark(maze, cur);
if(IsExit(maze, cur, entry))
{
printf("找到了一条路\n");
return;
}
//递归时更新 cur, (每次递归时, 这里的点是下次要走的点, 无论能不能走交给递归判断)
Point up = cur;
up.row -= 1;
_GetPath(maze, up, entry);
Point right = cur;
right.col += 1;
_GetPath(maze, right, entry);
Point down = cur;
down.row += 1;
_GetPath(maze, down, entry);
Point left = cur;
left.col -= 1;
_GetPath(maze, left, entry);
}
else
{
return;
}
}
void GetPath(Maze* maze, Point entry)
{
if(maze == NULL)
{
return;//非法输入
}
if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL)
{
return;
}
//辅助完成递归
_GetPath(maze, entry, entry);
MazePrint(maze);
}
4.判断是否可以落脚
即先判断迷宫数据结构是否输入合法, 接下来就是判断当前位置是否合法, 如果不合法就退出, 如果当前位置对应的值是 1, 则说明能落脚, 否则就说明不能落脚.
int CanStay(Maze* maze, Point cur)
{
if(maze == NULL)
{
return 0;
}
if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL)
{
return 0;
}
if(maze -> map[cur.row][cur.col] == 1)
{
return 1;
}
return 0;
}
5.判断出口
如果该位置到达迷宫边界, 并且不等于入口位置, 则说明到达出口
int IsExit(Maze* maze, Point cur, Point entry)
{
if(maze == NULL)
{
return 0;
}
if(cur.row == entry.row && cur.col == entry.col)
{
return 0;
}
if(cur.row == MAX_ROW -1 || cur.row == 0 || cur.col ==MAX_COL -1 || cur.col == 0)
{
return 1;
}
return 0;
}
6.标记
将当前位置的值赋值为2
void Mark(Maze* maze, Point cur)
{
if(maze == NULL)
{
return;
}
if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL)
{
return;
}
maze -> map[cur.row][cur.col] = 2;
}
7.打印迷宫函数
void MazePrint(Maze* maze)
{
if(maze == NULL)
{
return;//非法输入
}
int row = 0;
int col = 0;
for(; row < MAX_ROW; row++)
{
for(col = 0; col < MAX_COL; col++)
{
printf("%2d ", maze -> map[row][col]);
}
printf("\n");
}
}
依次将回溯点打印出来,运行结果如图