有多条通路且带环的迷宫如图所示:
但是由于还有其他路线,且出口一致,所以不能采用封路的办法,我们可以这样做,走每一步之前,先用当前位置的值加一标记下一步要走的位置,判断下一步是否是通路除了,值为一,也可以是,当前位置的值小于下一步位置的值。解决迷宫问题的思维导图如下具体代码实现如下, 所依赖的栈可参考https://blog.csdn.net/virgofarm/article/details/80065574:
Maze.h
#pragma once
#define MAX_ROW 4
#define MAX_COL 4
typedef struct Position
{
int _x;
int _y;
}Position;
typedef struct Maze
{
int _map[MAX_ROW][MAX_COL];
}Maze, *PMaze;
void InitMaze(PMaze pm, int map[][MAX_COL]);
int _PassMaze(PMaze pm, Position entry, Position cur, PStack PPath, PStack PShortPath);
int IsExit(PMaze pm, Position cur, Position entry);
int IsValidEntry(PMaze pm, Position entry);
void PassMaze(PMaze pm, Position entry, PStack ps);
void PrintMaze(PMaze pm, int map[][MAX_COL]);
Maze.c
//打印迷宫
void PrintMaze(PMaze pm)
{
int i = 0;
assert(pm);
for (; i < MAX_ROW; ++i)
{
int j = 0;
for (; j < MAX_COL; ++j)
{
printf("%d ", pm->_map[i][j]);
}
printf("\n");
}
}
//迷宫初始化,就是将地图中的值赋给迷宫
void InitMaze(PMaze pm, int map[][MAX_COL])
{
int i = 0;
assert(pm);
for (; i < MAX_ROW; ++i)
{
int j = 0;
for (; j < MAX_COL; ++j)
{
pm->_map[i][j] = map[i][j];
}
}
}
//检测迷宫入口是否合法
int IsValidEntry(PMaze pm, Position entry)
{
assert(pm);
//必须位于迷宫边界且值为1
if ((entry._x == 0 || entry._y == 0 || entry._x == MAX_ROW - 1
|| entry._y == MAX_COL - 1) && (pm->_map[entry._x][entry._y] == 1))
return 1;
return 0;
}
int IsPass(PMaze pm, Position cur, Position next)
{
assert(pm);
//next值为1且不能越界
if ((next._x >= 0 && next._x <= MAX_ROW - 1) &&
(next._y >= 0 && next._y <= MAX_COL - 1) &&
pm->_map[next._x][next._y] == 1)
return 1;
//next值大于cur值且不能越界
if ((cur._x >= 0 && cur._x <= MAX_ROW - 1) &&
(cur._y >= 0 && cur._y <= MAX_COL - 1) &&
pm->_map[cur._x][cur._y] < pm->_map[next._x][next._y])
return 1;
return 0;
}
//检测是否是出口
int IsExit(PMaze pm, Position cur, Position entry)
{
assert(pm);
//因为之前已经走过了,所以只要处于边界且不是入口肯定是出口
if ((cur._x == 0 || cur._x == MAX_ROW - 1 ||
cur._y == 0 || cur._y == MAX_COL - 1) &&
((cur._x != entry._x) || (cur._y != entry._y)))
return 1;
return 0;
}
void UpdatePath(PStack PPath, PStack PShortPath)
{
int i = 0;
int size = 0;
assert(PPath);
assert(PShortPath);
PShortPath->size = PPath->size;
size = PPath->size;
for (; i < size; i++)
PShortPath->arr[i] = PPath->arr[i];
}
int _PassMaze(PMaze pm, Position entry, Position cur, PStack PPath, PStack PShortPath)
{
Position next;
assert(pm);
assert(PPath);
assert(PShortPath);
//栈如果为空说明进来的是入口
if (!StackSize(PPath))
pm->_map[cur._x][cur._y] = 2;
StackPush(PPath, cur);
//判断是否为出口
if (IsExit(pm, cur, entry))
{
//更新最短路径:1.PShortPath为空2.PShortPath的size大于PPath的size
if (StackEmpty(PShortPath))
UpdatePath(PPath, PShortPath);
if (StackSize(PPath) < StackSize(PShortPath))
UpdatePath(PPath, PShortPath);
//将PPath中的栈顶元素出栈,继续找路径
StackPop(PPath);
}
//上
next = cur;
next._x -= 1;
if (IsPass(pm, cur, next))
{
//先用cur的值加1标记next位置,再走next
pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
_PassMaze(pm, entry, next, PPath, PShortPath);
}
//左
next = cur;
next._y -= 1;
if (IsPass(pm, cur, next))
{
pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
_PassMaze(pm, entry, next, PPath, PShortPath);
}
//右
next = cur;
next._y += 1;
if (IsPass(pm, cur, next))
{
pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
_PassMaze(pm, entry, next, PPath, PShortPath);
}
//下
next = cur;
next._x += 1;
if (IsPass(pm, cur, next))
{
pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
_PassMaze(pm, entry, next, PPath, PShortPath);
}
//说明cur走错了
StackPop(PPath);
return 0;
}
void PassMaze(PMaze pm, Position entry, PStack ps)
{
Stack PShortPath;
assert(pm);
assert(ps);
//先判断迷宫入口是否合法
if (!IsValidEntry(pm, entry))
{
printf("迷宫入口非法!!!\n");
return;
}
//开始真的走进入口
_PassMaze(pm, entry, entry, ps, &PShortPath);
}
test.c
#include "stack.h"
#include "Maze.h"
#include <windows.h>
void TestMaze(PStack ps)
{
int i = 0;
Position entry;
Maze m;
PMaze pm = &m;
StackInit(ps, 10);
int map[4][4] = { { 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 0 }};
InitMaze(pm, map);
PrintMaze(pm, map);
entry._x = 3;
entry._y = 1;
PassMaze(pm, entry, ps);
printf("\n");
PrintMaze(pm, map);
}
int main()
{
Stack s;
PStack ps = &s;
TestMaze(ps);
system("pause");
return 0;
}