二维迷宫之中,找出出口,并且输出路径。数据结构中的迷宫求解问题。
程序中,建立二维数组为迷宫,0为墙壁,1为可以通行的道路。
PosType为坐标(结构体);
算法的基本思想是:若当前位置“可通”,则纳入“当前路径”,并继续朝“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直到出口,若当前位置“不可通过”,则应顺着“来向”退回到“前一块道块”,然后朝着“来向”之外的其他方向继续探索。若4个方向都不可通过,则应从“当前路径”上删除该通道块。
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR -1
#define FALSE 0
#define TRUE 1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100 //初始分配增量
#define STACKINCREMENT 10 //分配增量
//重定义:
typedef int Status;
typedef int MazeType; //迷宫
typedef struct{ //坐标的重定义
int x;
int y;
}PosType;
typedef struct{
int ord; //通道块在路径上的“序号”
PosType seat; //通道块在迷宫中的“坐标位置”
int di; //从此通道块走向下一通道块的“方向”
}SElemType;
typedef struct{
SElemType * base;
SElemType * top;
int stacksize; //当前已经分配的储存空间,以元素为单位
}SqStack;
//函数定义:
Status InitStack(SqStack &S); //构造一个空栈
Status Push(SqStack &S,SElemType e); //插入元素e为新的栈顶元素
Status StackEmpty(SqStack S); //若S为空栈,则返回TRUE,否则返回FAKSE
Status Pop(SqStack &S,SElemType &e); //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR
Status Pass(PosType curpos); //当前位置可以通过,即是未曾走到过的通道块
PosType NextPos(PosType curpos, int &n); //返回下一个坐标,
void FootPrint(PosType curpos); //记录足迹
void MarkPrint(PosType curpos); //留下不能同的标记,并返回上一步
Status shownumbers(SqStack S); //打印栈元素
Status MazePath(MazeType maze,PosType start,PosType end,SqStack &S); //前进函数,则求的一条存放在栈中,并返回TRUE,否则返回FALSE
//全局变量
//迷宫(二维数组)
MazeType maze[10][10] =
{
{0,0,0,0,0,0,0,0,0,0}, //0
{0,1,1,0,1,1,1,0,1,0}, //1
{0,1,1,0,1,1,1,0,1,0}, //2
{0,1,1,1,1,0,0,1,1,0}, //3
{0,1,0,0,0,1,1,1,1,0}, //4
{0,1,1,1,0,1,1,1,1,0}, //5
{0,1,0,1,1,1,0,1,1,0}, //6
{0,1,0,0,0,1,0,0,1,0}, //7
{0,0,1,1,1,1,1,1,1,0}, //8
{0,0,0,0,0,0,0,0,0,0}, //9
};
//函数实现
Status InitStack(SqStack &S)
{
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if(!S.base) //分配增量失败
exit(OVERFLOW);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status StackEmpty(SqStack S)
{
if(S.base == S.top)
return TRUE;
else
return FALSE;
}
Status Push(SqStack &S,SElemType 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)
{
if(S.base == S.top)
return ERROR;
e = *--S.top;
return OK;
}
Status Pass(PosType curpos)
{
if(maze[curpos.y][curpos.x] == 1)
return OK;
else
return FALSE;
}
PosType NextPos(PosType curpos,int &n)
{
//东-1,西-2,南-3,北-4
switch(n)
{
case 1: //东
curpos.x++;
if(maze[curpos.y][curpos.x] !=2)
break;
curpos.x--;
case 2: //南
curpos.y++;
n = 2;
if(maze[curpos.y][curpos.x] !=2)
break;
curpos.y--;
case 3: //西
curpos.x--;
n=3;
if(maze[curpos.y][curpos.x] !=2)
break;
curpos.x++;
case 4: //北
curpos.y--;
n=4;
if(maze[curpos.y][curpos.x] == 2)
{
curpos.y++;
maze[curpos.y][curpos.x] = 0;
}
break;
}
return curpos;
}
Status MazePath(MazeType maze,PosType start,PosType end,SqStack &S)
{
// SqStack S;
PosType curpos;
SElemType e;
// InitStack(S);
curpos = start; //设定当前位置为入口位置
int curstep = 1; //探索第一步
do
{
if(Pass(curpos)) //当前位置可以通过,即是未曾走到过的通道块
{
FootPrint(curpos); //留下足迹
e.ord = curstep;e.di = 1;e.seat = curpos;
Push(S,e); //加入路径
if(curpos.x == end.x && curpos.y == end.y)
return (TRUE); //到达终点(出口)
curpos = NextPos(curpos,e.di); //下一个位置是当前位置的东临
curstep++; //探索下一步
}
else //当前位置不能通过
{
if(!StackEmpty(S))
{
Pop(S,e);
while(e.di == 4 && !StackEmpty(S)) //当前位置4个方向都测试无法通过的情况下
{
MarkPrint(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);
}
void FootPrint(PosType curpos)
{
maze[curpos.y][curpos.x] = 2; //设2为通过的路径
}
void MarkPrint(PosType curpos)
{
maze[curpos.y][curpos.x] = 0; //通不过的用墙壁0代替
}
Status shownumbers(SqStack S)
{
int numbers = 1;
if(S.top == S.base)
{
printf("栈为空栈,无法打印\n");
exit(-1);
}
while(S.base < S.top)
{
S.top--;
printf("序号 %d: 坐标:%4d%4d\n",numbers,S.top->seat.x+1,S.top->seat.y+1);
numbers++;
}
}
//启动函数
int main()
{
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
printf("%4d",maze[i][j]);
printf("\n");
}
SqStack S; //建立栈
InitStack(S); //
PosType start; //入口
PosType end; //出口
start.x = 1;start.y = 1; //入口坐标
end.x = 8;end.y = 8; //出口坐标
if(MazePath(maze[10][10],start,end,S))
{
printf("------------------------------------------\n");
printf(" 成功找到路径!\n");
shownumbers(S);
}
return 0;
}
直接上的代码,中间有注释。运用栈来实现,也可以运用递归回溯法。