迷宫求解的思路很简单,即所谓的“穷举求解”,从入口出发,顺某一方向探索,若能走通,则继续往前走,否则沿着原路退回,换一个方向继续探索,直至所有可能的通路都探索到为止。
测试:
运行结果:
![](https://img-blog.csdn.net/20140410122823937?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20140410122952390?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20140410123011953?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
为了保证在任何位置上都能沿着原路返回,需要使用栈来保存从入口到当前位置的路径。
这里采用之前介绍的顺序栈作为容器存储路径。
具体实现:
/****************************************
使用栈进行迷宫求解
by Rowandjj
2014/4/10
*****************************************/
#include<iostream>
using namespace std;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define ERROR 0
#define OVERFLOW 0
#define TRUE 1
#define FALSE 0
//------------------迷宫求解----------------------------------
typedef struct _POSTYPE_//坐标类型
{
int x;//行
int y;//列
}PosType;
#define MAXLENGTH 25
typedef int MazeType[MAXLENGTH][MAXLENGTH];
MazeType m;//迷宫数组
int curstep = 1;//当前足迹,初值为1
typedef struct _SELEMTYPE_//栈元素类型
{
int ord;//序号
PosType seat;//当前坐标
int di;//下一方向(0-3分别代表东南西北)
}SElemType;
//-------------------栈定义------------------------------------
typedef int Status;
typedef struct _STACK_//栈的顺序存储结构
{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针,始终指在栈顶下一个元素
int stacksize;//栈容量
}SqStack;
/*栈操作定义*/
Status InitStack(SqStack *S);
Status DestroyStack(SqStack *S);
Status ClearStack(SqStack *S);
Status StackEmpty(SqStack S);
int StackLength(SqStack S);
Status GetTop(SqStack S,SElemType *e);
Status Push(SqStack *S,SElemType e);
Status Pop(SqStack *S,SElemType *e);
Status StackTraverse(SqStack S,Status(*visit)(SElemType));
Status visit(SElemType e);
/*栈实现*/
Status InitStack(SqStack *S)
{
(*S).base = (SElemType*)malloc(sizeof(SElemType)*STACK_INIT_SIZE);
if(!(*S).base)
{
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
Status DestroyStack(SqStack *S)
{
free((*S).base);
(*S).base = (*S).top = NULL;
(*S).stacksize = 0;
return OK;
}
Status ClearStack(SqStack *S)
{
(*S).top = (*S).base;
return OK;
}
Status StackEmpty(SqStack S)
{
if(S.top == S.base)
{
return TRUE;
}
else
{
return FALSE;
}
}
int StackLength(SqStack S)
{
return S.top-S.base;
}
Status GetTop(SqStack S,SElemType *e)
{
*e = *(--S.top);
return OK;
}
Status Push(SqStack *S,SElemType e)
{
if((*S).top - (*S).base >= STACK_INIT_SIZE)
{
(*S).base = (SElemType *)realloc((*S).base,(STACK_INIT_SIZE + 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)
{
if((*S).top == (*S).base)
{
return ERROR;
}
*e = *--(*S).top;
return OK;
}
Status StackTraverse(SqStack S,Status(*vi)(SElemType))
{
while(S.top>S.base)
{
vi(*S.base++);
}
cout<<endl;
return OK;
}
Status visit(SElemType e)
{
cout<<"("<<e.seat.x<<","<<e.seat.y<<")"<<" ";
return OK;
}
//---------------迷宫求解算法-------------------------
//定义墙元素值为0,可通过路径为1,不能通过路径为-1,通过路径为足迹
Status Pass(PosType b)//判断当前路径是否可以通过
{
if(m[b.x][b.y] == 1)
{
return OK;
}
else
{
return ERROR;
}
}
void FootPrint(PosType a)//使迷宫m的a点的序号变为足迹(curstep)
{
m[a.x][a.y] = curstep;
}
PosType NextPos(PosType c,int di)//根据当前位置及移动方向,返回下一位置
{
PosType direc[4] = {{0,1},{1,0},{0,-1},{-1,0}};//行增量,列增量
c.x += direc[di].x;
c.y += direc[di].y;
return c;
}
void MarkPrint(PosType b)//使迷宫m的b点的序号变为-1(不能通过的路径)
{
m[b.x][b.y] = -1;
}
//若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
Status MazePath(PosType start,PosType end)
{
SqStack S;
PosType curpos;
SElemType e;
InitStack(&S);
curpos = start;
do
{
if(Pass(curpos))//当前位置可通
{
FootPrint(curpos);//留下足迹
e.ord = curstep;
e.seat.x = curpos.x;
e.seat.y = curpos.y;
e.di = 0;
Push(&S,e);//入栈当前位置及状态
curstep++;
if(curpos.x == end.x && curpos.y == end.y)//当前位置是出口
{
cout<<"路径如下"<<endl;
StackTraverse(S,visit);
return TRUE;
}
curpos = NextPos(curpos,e.di);//当前若不是出口则继续判断下一个位置
}else//当前位置不可通
{
if(!StackEmpty(S))
{
Pop(&S,&e);//当前位置出栈
curstep--;
while(e.di == 3 && !StackEmpty(S))//前一位置处于最后一个方向(北)
{
MarkPrint(e.seat);
Pop(&S,&e);
curstep--;
}
if(e.di < 3)//还有其他方向没有探索
{
e.di++;//换下一个方向探索
Push(&S,e);//改变方向后重新入栈
curstep++;
curpos = NextPos(e.seat,e.di);
}
}
}
} while (!StackEmpty(S));
return FALSE;
}
测试:
//--------------------测试------------------------------------
void Print(int x,int y)
{ /* 打印迷宫 */
int i,j;
for(i=0;i<x;i++)
{
for(j=0;j<y;j++)
printf("%3d",m[i][j]);
printf("\n");
}
}
int main()
{
PosType begin,end;
int i,j,x,y,x1,y1;
cout<<"请输入迷宫的行数,列数(包括外墙):";
cin>>x;
cin>>y;
for(i=0;i<x;i++) /* 定义周边值为0(同墙) */
{
m[0][i]=0; /* 行周边 */
m[x-1][i]=0;
}
for(j=1;j<y-1;j++)
{
m[j][0]=0; /* 列周边 */
m[j][y-1]=0;
}
for(i=1;i<x-1;i++)
for(j=1;j<y-1;j++)
m[i][j]=1; /* 定义通道初值为1 */
cout<<"请输入迷宫内墙单元数:";
cin>>j;
cout<<"请依次输入迷宫内墙每个单元的行数,列数:\n";
for(i=1;i<=j;i++)
{
cin>>x1;
cin>>y1;
m[x1][y1]=0; /* 定义墙的值为0 */
}
cout<<"迷宫结构如下:\n";
Print(x,y);
cout<<"请输入起点的行数,列数:";
cin>>begin.x;
cin>>begin.y;
cout<<"请输入终点的行数,列数:";
cin>>end.x;
cin>>end.y;
if(MazePath(begin,end)) /* 求得一条通路 */
{
cout<<"此迷宫从入口到出口的一条路径如下:\n";
Print(x,y); /* 输出此通路 */
}
else
printf("此迷宫没有从入口到出口的路径\n");
return 0;
}
运行结果:
解:
栈中保存的路径:
这里还可以使用递归来
求出所有的解:
实现方式:
#include<IOSTREAM>
using namespace std;
typedef struct _POSTYPE_
{
int x;//行值
int y;//列值
}PosType;
#define MAXLENGTH 25
typedef int MazeType[MAXLENGTH][MAXLENGTH];//迷宫类型
PosType end;//终点
MazeType m;//迷宫
int x,y;//迷宫行数,列数
/* 定义墙元素值为0,可通过路径为-1,通过路径为足迹 */
void Print(int x,int y)
{ /* 输出解 */
int i,j;
for(i=0;i<x;i++)
{
for(j=0;j<y;j++)
printf("%3d",m[i][j]);
printf("\n");
}
printf("\n");
}
void Try(PosType cur,int curstep)//试探
{
int i;
PosType next;//下一位置
PosType direc[4] = {{0,1},{1,0},{0,-1},{-1,0}};//依次为东南西北
for(i = 0 ; i <= 3; i++)
{
next.x = cur.x+direc[i].x;
next.y = cur.y+direc[i].y;
if(m[next.x][next.y] == -1)//是通路
{
m[next.x][next.y] = ++curstep;
if(next.x != end.x || next.y != end.y)//若不是终点继续递归调用
{
Try(next,curstep);
}
else
{
system("pause");
Print(x,y);//输出结果
}
m[next.x][next.y] = -1;//恢复为通路,试探下一条路
curstep--;
}
}
}
int main()
{
PosType begin;
int i,j,x1,y1;
printf("请输入迷宫的行数,列数(包括外墙):");
cin>>x;
cin>>y;
for(i=0;i<x;i++) /* 定义周边值为0(同墙) */
{
m[0][i]=0; /* 行周边 */
m[x-1][i]=0;
}
for(j=1;j<y-1;j++)
{
m[j][0]=0; /* 列周边 */
m[j][y-1]=0;
}
for(i=1;i<x-1;i++)
for(j=1;j<y-1;j++)
m[i][j]=-1; /* 定义通道初值为-1 */
printf("请输入迷宫内墙单元数:");
cin>>j;
if(j)
printf("请依次输入迷宫内墙每个单元的行数,列数:\n");
for(i=1;i<=j;i++)
{
cin>>x1;
cin>>y1;
m[x1][y1]=0;
}
printf("迷宫结构如下:\n");
Print(x,y);
printf("请输入起点的行数,列数:");
cin>>begin.x;
cin>>begin.y;
printf("请输入终点的行数,列数:");
cin>>end.x;
cin>>end.y;
m[begin.x][begin.y]=1;
Try(begin,1); /* 由第一步起点试探起 */
return 0;
}