迷宫求解(栈实现)

二维迷宫之中,找出出口,并且输出路径。数据结构中的迷宫求解问题。

程序中,建立二维数组为迷宫,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;
  } 
 

直接上的代码,中间有注释。运用栈来实现,也可以运用递归回溯法。

猜你喜欢

转载自blog.csdn.net/rage_/article/details/63259691
今日推荐