迷宫求解
求解思路
利用计算机进行迷宫求解的最简单的方法就是穷举法。
具体思路如下(参考清华大学出版社数据结构C语言版):
首先,从入口出发,顺着某一方向向前探索,若能走通,就继续前进,若走不通则按原路返回,换个方向继续前进,直至所有可能的通路都走过为止。该思路与栈的特点十分相似,按照一定的顺序方向,每走一步将该步压入栈,如果遇到不能走或者下一步方向的方格已经走过时,就把当前步弹出栈。直到走到迷宫的终点为止。
相关代码
//base.h
#ifndef BASE_H
#define BASE_H
#include<cstdio>
#include<cstdlib>
#include<malloc.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int DirectiveType;
typedef struct {
int row;
int col;
}PosType;//通道块类型,代表的坐标(行,列)
typedef struct {
int step;//在路径中的序号
PosType seat;//位置坐标
DirectiveType di;//方向 1代表东 2代表南 3代表西 4 代表北
}SElemType;//栈元素类型,
#endif // !BASE_H
//Map.h
#ifndef MAP_H
#define MAP_H
#include "Stack.h"
#define ROW 10
#define COL 10
#define RANGE 100
typedef struct {
int m, n;
int arr[RANGE][RANGE];
}MazeType;
Status InitMaze(MazeType &Maze, int a[][COL], int row, int col);
Status Pass(MazeType Maze, PosType CurPos);
Status FootPrint(MazeType &Maze, PosType CurPos);
Status MarkPrint(MazeType &Maze, PosType CurPos); //形参为地图的引用,以及当前位置,函数作用将当前位置置为走过但不能通过
SElemType CreatSElem(int step, PosType pos, int di);
PosType NextPos(PosType CurPos, DirectiveType di); //返回值为下一步位置,形参当前位置坐标变量 当前移动方向
Status PosEquare(PosType Pos1, PosType Pos2); //形参为两个坐标,函数用来判断是否到达终点
void PrintMaze(MazeType Maze); //打印迷宫
Status MazePath(MazeType &Maze, PosType start, PosType end); //寻找迷宫路径,形参包括(迷宫的引用,起点坐标,终点坐标)
#endif // !MAP_H
//Stack.h
#include "base.h"
typedef struct {
SElemType *base;
SElemType *top;
int stackSize;
}SqStack;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
Status InitStack(SqStack &S);
Status GetTop(SqStack S, SElemType &e);
Status Push(SqStack &s, SElemType e);
Status Pop(SqStack &s, SElemType &e);
Status StackEmpty(SqStack s); Status DestroyStack(SqStack &s);
Status ClearStack(SqStack &s);
int StackLength(SqStack s);
Status StackTraverse(SqStack s, Status(*visit)(SElemType e));
//Map.cpp
#include "Map.h"
Status InitMaze(MazeType &Maze, int a[][COL], int row, int col)
{
//初始化map地图
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= col; j++)
Maze.arr[i][j] = a[i - 1][j - 1];
}
for (int j = 0; j <= col + 1; j++)
Maze.arr[0][j] = Maze.arr[row + 1][j] = 1;
for (int i = 0; i <= row + 1; i++)
Maze.arr[i][0] = Maze.arr[i][col + 1] = 1;
Maze.m = row;
Maze.n = col;
return OK;
}
Status Pass(MazeType Maze, PosType CurPos)
{
//形参地图,位置, 判断该位置是否走过
if (Maze.arr[CurPos.row][CurPos.col] == 0)
return 1;
else return 0;
}
Status FootPrint(MazeType &Maze, PosType CurPos)
{
Maze.arr[CurPos.row][CurPos.col] = 2;//通的过,留下足迹
return OK;
}
Status MarkPrint(MazeType &Maze, PosType CurPos) //形参为地图的引用,以及当前位置,函数作用将当前位置置为走过但不能通过
{
Maze.arr[CurPos.row][CurPos.col] = 3;//走过但是不能通过
return OK;
}
SElemType CreatSElem(int step, PosType pos, int di)
{
//返回值为栈元素,函数作用为初始化栈元素并返回
SElemType e;
e.step = step;
e.di = di;
e.seat = pos;
return e;
}
PosType NextPos(PosType CurPos, DirectiveType di) //返回值为下一步位置,形参当前位置坐标变量 当前移动方向
{
PosType Pos = CurPos;
switch (di)
{
case 1:Pos.col++; break;//East
case 2:Pos.row++; break;//south
case 3:Pos.col--; break;//west
case 4:Pos.row--; break;//north
}
return Pos;
}
Status PosEquare(PosType Pos1, PosType Pos2) //形参为两个坐标,函数用来判断是否到达终点
{
if (Pos1.col == Pos2.col && Pos1.row == Pos2.row)
return 1;
else return 0;
}
void PrintMaze(MazeType Maze) //打印迷宫
{
int i, j;
printf(" ");
for (i = 0; i <= COL + 1; i++)
printf("%2d", i);
printf("\n");
for (i = 0; i <= ROW + 1; i++)
{
printf("%2d", i);
for (j = 0; j <= COL + 1; j++)
{
switch (Maze.arr[i][j])
{
case 0:printf(" "); break;//没有走过
case 2:printf(" *"); break;//走过且走的通
case 3:printf(" "); break;//走过但不通
case 1:printf(" #"); break;//障碍
}
}
printf("\n");
}
}
Status MazePath(MazeType &Maze, PosType start, PosType end) //寻找迷宫路径,形参包括(迷宫的引用,起点坐标,终点坐标)
{
SqStack S; //路径栈
SElemType e; //栈元素,包含(位置,步数,下一步方向)
InitStack(S); //初始化栈
PosType CurPos = start; //声明当前坐标初始化为开始坐标
int Curstep = 1; //当前步数
do
{
if (Pass(Maze, CurPos)) //如果没走过
{
FootPrint(Maze, CurPos); //在该位置留下足迹
e = CreatSElem(Curstep, CurPos, 1); //将当前位置,步数,以及移动方向初始化为栈元素赋值给e
Push(S, e); //将e压入栈
if (PosEquare(CurPos, end)) return TRUE; //判断是否到达终点,如果是返回
CurPos = NextPos(CurPos, 1); //移动到下一位置并将移动方向置为右
Curstep++; //当前步数加一
}
else
{ //如果走过
if (!(StackEmpty(S))) //如果栈不空
{
Pop(S, e); //弹出栈顶元素
while (e.di == 4 && !StackEmpty(S)) //当当前栈顶元素的当前步数方向为向上并且栈不空
{
MarkPrint(Maze, e.seat); //将当前位置置为走过但不通
Pop(S, e); //弹出
}
if (e.di < 4) //如果当前位置的方向不为上
{
e.di++; Push(S, e); //将方向置为下一步的方向,压入栈
CurPos = NextPos(e.seat, e.di); //移动到下一位置
}
}
}
} while (!StackEmpty(S));
return FALSE;
}
//Stack.cpp
#include "Stack.h"
Status InitStack(SqStack &S) {
//初始化一个空栈
S.base = (SElemType* )malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base)
exit(ERROR);
S.top = S.base;
S.stackSize = STACK_INIT_SIZE;
return OK;
}
Status GetTop(SqStack S, SElemType &e) {
//若栈不空,则用e返回栈顶元素,并返回ok,否则返回ERROR
if (S.top == S.base)
return ERROR;
e = *(S.top - 1);
return OK;
}
Status Push(SqStack &s, SElemType e) {
//将e压入到栈中
if (s.top - s.base >= s.stackSize) {
s.base = (SElemType *)realloc(s.base, (s.stackSize + STACKINCREMENT) * sizeof(SElemType));
if (!s.base)
exit(OVERFLOW);
s.top = s.base + s.stackSize;
s.stackSize += STACKINCREMENT;
}
*s.top++ = e;
return OK;
}
Status Pop(SqStack &s, SElemType &e) {
//若栈不空,则删除S的栈顶元素,用e返回其中值,并返回ok,否则返回ERROR
if (s.top == s.base)
return ERROR;
e = *--s.top;
return OK;
}
Status StackEmpty(SqStack s) {
//若栈为空栈,则返回true,否则返回false
if (s.base == s.top)
return TRUE;
else
return FALSE;
}
Status DestroyStack(SqStack &s) {
//销毁栈,使得栈不存在
if (s.base) {
free(s.base);
s.base = NULL;
s.top = NULL;
s.stackSize = 0;
return OK;
}
}
Status ClearStack(SqStack &s) {
//清空栈
if (s.base) {
s.top = s.base;
}
return OK;
}
int StackLength(SqStack s) {
//返回栈的长度
return s.top - s.base;
}
Status StackTraverse(SqStack s, Status(*visit)(SElemType e)) {
while (s.top>s.base)
{
visit(*s.base++);
}
printf("\n");
return OK;
}
Status visit(SElemType e) {
printf("%d ", e);
return OK;
}
//main.cpp
#include "map.h"
int R[10][10] = {
{0,0,1,0,0,0,0,1,0,1},
{1,0,1,0,1,1,0,1,1,0},
{1,0,0,0,1,1,0,0,0,1},
{0,1,0,1,1,0,0,1,1,1},
{0,1,0,0,1,1,0,1,0,0},
{1,0,1,0,1,1,0,0,1,0},
{0,1,1,0,0,0,1,0,1,1},
{0,1,0,1,1,0,0,0,0,0},
{0,1,1,0,0,1,1,1,1,0},
{1,0,1,0,1,1,0,0,1,0} };
int main()
{
char cmd; int i, j;
PosType start, end;
MazeType Maze;
printf(" ");
for (i = 1; i <= COL; i++)
printf("%2d", i);
printf("\n");
for (i = 0; i < ROW; i++)
{
printf("%2d", i + 1);
for (j = 0; j < COL; j++)
printf("%2d", R[i][j]);
printf("\n");
}
InitMaze(Maze, R, ROW, COL);
printf("\n迷宫入口坐标:");
scanf("%d%d", &start.row, &start.col);
printf("\n迷宫出口坐标:");
scanf("%d%d", &end.row, &end.col);
if (MazePath(Maze, start, end))
{
PrintMaze(Maze);
}
else
{
printf("\nNO WAY");
}
system("pause");
return 0;
}
该代码栈部分参考清华数据结构,将栈与map分装成头文件,再用相应的文件进行实现,比较整洁,建议可以考虑这么做。
来源:https://blog.csdn.net/qq_32577169/article/details/102754144