栈的应用——迷宫

本文共总结三个方法:

1,  迷宫不带环(循环法)2,迷宫不带环(递归法)3,迷宫带环(递归法)

 

 

一,迷宫不带环(循环法)的基本思路:

  通过栈来保存路径,首先将初始位置入栈,后用取出栈顶元素的方式,得到初始位置,

  然后进入while循环,循环内有4种情况,找到出口,向四个方向走动,走错了,找              

  不到出口(栈空了)。

 

  若可以向四个方向走通,则将next位置入栈,并用continue返回到循环初始语句,

  我们为可以走通的位置赋值2,以标记路径,一直走会找到出口,出循环,结束程序

  或者走错了

 

  为走错的位置赋值3,以表示此路不通,并出栈当前位置,回到循环头,一直出栈会        使栈空而退出,或者找到可以走通的位置

 

     

  循环会在找到出口或栈空了的时候退出,除循环后需判断是那种原因退出

 

头文件

#ifndef __MAZE_H__
#define __MAZE_H__

//#pragma once

#include"StackD.h"

#define MAX_ROW 6
#define MAX_LOW 6

typedef struct Maze
{
  int _map [MAX_ROW][MAX_LOW];
}Maze;



//初始化 迷宫
void InitMaze(Maze* m  );

//打印迷宫
void PrintMaze(Maze*m);



//判断入口是否有效
int IsValidEnter(Maze*m,Position enter);

//判断当前这步能否走通
int IsPass(Maze * m,Position cur);

//走迷宫(循环法)
void PassMazeNor(Maze* m,Position enter ,StackD *s);

//判断出口
int IsMazeExit(Maze* m,Position cur,Position enter);


#endif //__MAZE_H__

 

函数文件

//#include"Maze.h"
//
//void InitMaze(Maze* m)
//{
//	int map[MAX_ROW][MAX_LOW]={
//		{0,0,0,0,0,0},
//		{0,0,1,0,0,0},
//		{0,0,1,0,0,0},
//		{0,0,1,1,1,0},
//		{0,0,1,0,1,1},
//		{0,0,1,0,0,0}
//	};
//	
//	int i=0;
//	int j=0;
//    assert(m);
//	for(;i<MAX_ROW;i++)
//	{
//		j=0;
//	  for(;j<MAX_LOW;j++)
//	  {
//		  m->_map[i][j]=map[i][j];
//	  }
//	}
//}
//
//void PrintMaze(Maze*m)
//{
//    int i=0;
//	int j=0;
//    assert(m);
//	for(;i<MAX_ROW;i++)
//	{
//		j=0;
//	  for(;j<MAX_LOW;j++)
//	  {
//		  printf("%d ",m->_map[i][j]);
//	  }
//	  printf("\n");
//	}
//}
//
判断入口是否有效
//int IsValidEnter(Maze*m,Position enter)
//{  
//   assert(m);
//   if(1==m->_map[enter._x][enter._y])
//   {
//     return 1;
//   }
//   return 0;
//}
//
//
判断当前这步能否走通
//int IsPass(Maze * m,Position cur)
//{
//  assert(m);越界问题
//  处理
//  if(1==m->_map[cur._x][cur._y]&&((cur._x<=MAX_ROW-1)&&(cur._x>=0)&&(cur._y<=MAX_LOW-1)&&(cur._y>=0)))
//  {
//     return 1;
//  }
//  return 0;
//}
//
判断出口
//int IsMazeExit(Maze* m,Position cur,Position enter)
//{
//	if((cur._x==enter._x)&&(cur._y==enter._y))
//	{
//	 return 0;
//	}
//	if(0==cur._x||0==cur._y||MAX_ROW-1==cur._x||MAX_LOW-1==cur._y)
//	{
//	  return 1;
//	}
//	return 0;
//}
//
//
走迷宫
//void PassMazeNor(Maze* m,Position enter ,StackD *s)
//{
//	Position cur;
//	Position next;
//  assert(m);
//  
//  //判断入口是否有效
//  if(1!=IsValidEnter(m,enter))
//  {
//    printf("无效入口!\n");
//	return ;
//  }
//  m->_map[enter._x][enter._y]=2;
//  // 入栈 
//  StackDPush(s,  enter);
//  while(StackDEmpty(s))//将出口也出栈时,栈内为空,越界问题以处理
//  {
//
//	 
//	  
//	   cur=StackDTop(s);
//		m->_map[cur._x][cur._y]=2;
//	    //判断是否找到出口
//	   if(IsMazeExit(m,cur,enter))
//	   {
//	     break;
//	   }
//	  
//	   
//    //上
//		next=cur;
//		next._x-=1;
//		if(IsPass(m,next))//判断向上能否走通
//		{
//		   // 入栈 
//		StackDPush(s, next);
//		continue;
//		}
//    //左
//		next=cur;
//		next._y-=1;
//		if(IsPass(m,next))//判断向左能否走通
//		{
//		   // 入栈 
//		StackDPush(s, next);
//		continue;
//		}
//    //右
//		next=cur;
//		next._y+=1;
//		if(IsPass(m,next))//判断向右能否走通
//		{
//		   // 入栈 
//		StackDPush(s, next);
//		continue;
//		}
//	//下
//		next=cur;
//		next._x+=1;
//		if(IsPass(m,next))//判断向下能否走通
//		
//		   // 入栈 
//			{
//			StackDPush(s, next);
//		    continue;
//			}
//	
//    //走错了
//
//		m->_map[cur._x][cur._y]=3;
//		// 出栈 
//		 StackDPop(s); 
//  }
//		//出循环的两种可能
//		//1,判断栈为空
//		if(!StackDEmpty(s))
//		{
//		  printf("迷宫没有出口!\n");
//		  return ;
//		}
//		//2,找到出口退出
//		printf("出口为%d ,%d",cur._x,cur._y);
//
//}


 

测试文件

//#include"Maze.h"
//
//
//Maze m;
//StackD s;
//
//
// 
//void TestMaze()
//{
//	Position enter;
//	
//	
//	enter._x=5;
//	enter._y=2;
//	StackDInit(&s);
//   InitMaze(&m);
//   PrintMaze(&m);
//   PassMaze(&m,enter );
//   PrintMaze(&m);
//}
//int main ()
//{
//	TestMaze();
//  return 0;
//}

 

二,迷宫不带环(递归法)的基本思路

 递归函数内有3种情况,找到出口,向四个方向走动,走错了。

 if(_PassMaze(m,enter,next))

         {

           return 1;

         }

 找到出口_PassMaze返回1,则if(_PassMaze(m,enter,next))条件成立,则所有_PassMaze函数返回,程序结束

 走错了返回0,if(_PassMaze(m,enter,next))条件不成立,当前函数不返回,测试下一个方向,测完所有方向发现走错了,  返回上级函数,重复动作,直到找到出口返回,或发现没有出口返回 

 

头文件

#ifndef __MAZE_H__
#define __MAZE_H__

//#pragma once

#include"StackD.h"

#define MAX_ROW 6
#define MAX_LOW 6

typedef struct Maze
{
  int _map [MAX_ROW][MAX_LOW];
}Maze;



//初始化 迷宫
void InitMaze(Maze* m  );

//打印迷宫
void PrintMaze(Maze*m);



//判断入口是否有效
int IsValidEnter(Maze*m,Position enter);

//判断当前这步能否走通
int IsPass(Maze * m,Position cur);



//判断出口
int IsMazeExit(Maze* m,Position cur,Position enter);
//递归法
void PassMaze(Maze* m,Position enter);
//递归体
int  _PassMaze(Maze*m,Position enter,Position cur);

#endif //__MAZE_H__

 

函数文件

#include"Maze.h"

void InitMaze(Maze* m)
{
	int map[MAX_ROW][MAX_LOW]={
		{0,0,0,0,0,0},
		{0,0,1,0,0,0},
		{0,0,1,0,0,0},
		{0,0,1,1,1,0},
		{0,0,1,0,1,1},
		{0,0,1,0,0,0}
	};
	
	int i=0;
	int j=0;
    assert(m);
	for(;i<MAX_ROW;i++)
	{
		j=0;
	  for(;j<MAX_LOW;j++)
	  {
		  m->_map[i][j]=map[i][j];
	  }
	}
}

void PrintMaze(Maze*m)
{
    int i=0;
	int j=0;
    assert(m);
	for(;i<MAX_ROW;i++)
	{
		j=0;
	  for(;j<MAX_LOW;j++)
	  {
		  printf("%d ",m->_map[i][j]);
	  }
	  printf("\n");
	}
}

判断入口是否有效
int IsValidEnter(Maze*m,Position enter)
{  
   assert(m);
   if(1==m->_map[enter._x][enter._y])
   {
     return 1;
   }
   return 0;
}


判断当前这步能否走通
int IsPass(Maze * m,Position cur)
{
  assert(m);越界问题
  处理
  if(1==m->_map[cur._x][cur._y]&&((cur._x<=MAX_ROW-1)&&(cur._x>=0)&&(cur._y<=MAX_LOW-1)&&(cur._y>=0)))
  {
     return 1;
  }
  return 0;
}

判断出口
int IsMazeExit(Maze* m,Position cur,Position enter)
{
	if((cur._x==enter._x)&&(cur._y==enter._y))
	{
	 return 0;
	}
	if(0==cur._x||0==cur._y||MAX_ROW-1==cur._x||MAX_LOW-1==cur._y)
	{
	  return 1;
	}
	return 0;
}



递归法
void PassMaze(Maze* m,Position enter)
{
  assert(m);
  
  判断入口是否有效
  if(1!=IsValidEnter(m,enter))
  {
    printf("无效入口!\n");
	return ;
  }
  _PassMaze(m,enter,enter);
}
递归体
int  _PassMaze(Maze*m,Position enter,Position cur)
{
	Position next;
   if(IsPass(m,cur))//是不是通路
   {
		 m->_map[cur._x][cur._y]=2;
     if(IsMazeExit(m,cur,enter))//是不是出口
	   {
		   //找到出口退出
		printf("出口为%d ,%d",cur._x,cur._y);

	     return 1;
	   }
	 //上
		next=cur;
		next._x-=1;
		if(_PassMaze(m,enter,next))
		{
		  return 1;
		}

		
	 //左
		next=cur;
		next._y-=1;
		if(_PassMaze(m,enter,next))
		{
		  return 1;
		}
	 //右
		next=cur;
		next._y+=1;
		if(_PassMaze(m,enter,next))
		{
		  return 1;
		}
	 //下
		next=cur;
		next._x+=1;
		if(_PassMaze(m,enter,next))
		{
		  return 1;
		}
		m->_map[cur._x][cur._y]=3;
	}
		return 0;
}

	

 

测试文件

//#include"Maze.h"
//
//
//Maze m;
//StackD s;
//
//
// 
//void TestMaze()
//{
//	Position enter;
//	
//	
//	enter._x=5;
//	enter._y=2;
//	StackDInit(&s);
//   InitMaze(&m);
//   PrintMaze(&m);
//   PassMaze(&m,enter );
//   PrintMaze(&m);
//}
//int main ()
//{
//	TestMaze();
//  return 0;
//}

 

 

三,迷宫带环(递归)

定义两个栈,path用来记录路径,shortpath用来记录最短路径

所谓更新栈,就是在shortpath为空,或者path的size小于shortpath的size时,将path的内容放入shortpath中

递归函数内有3种情况,找到出口,向四个方向走动,走错了。

 

找到出口了,更新栈,出栈入口 ,返回上级函数,继续测试其他方向,可能找到新的出口,更  

新栈,可能找不到而逐级退出

头文件

#ifndef  __LOOP_MAZE__
#define  __LOOP_MAZE__

#include"StackD.h"
#include<stdio.h>
#include<assert.h>


#pragma once



#define MAX_ROW 6
#define MAX_LOW 6

typedef struct Maze
{
  int _map [MAX_ROW][MAX_LOW];
}Maze;



//初始化 迷宫
void InitMaze(Maze* m  );

//打印迷宫
void PrintMaze(Maze*m);



//判断入口是否有效
int IsValidEnter(Maze*m,Position enter);

//判断当前这步能否走通
int _IsPass(Maze * m,Position next,Position cur);

//走迷宫(循环法)
void PassMazeNor(Maze* m,Position enter ,StackD *s);

//判断出口
int IsMazeExit(Maze* m,Position cur,Position enter);
//递归法
void PassMaze(Maze* m,Position enter,StackD* path,StackD*shortpath);
//递归体
void  _PassMaze(Maze*m,Position enter,Position cur,StackD* path,StackD*shortpath);



#endif //__LOOP_MAZE__

 

函数文件

#include"LoopMaze.h"

void InitMaze(Maze* m)
{
	int map[MAX_ROW][MAX_LOW]={
		{0,0,0,0,0,0},
		{0,1,1,1,0,0},
		{0,1,0,1,0,0},
		{0,1,0,1,0,0},
		{0,1,1,1,1,1},
		{0,1,0,0,0,0}
	};
	
	int i=0;
	int j=0;
    assert(m);
	for(;i<MAX_ROW;i++)
	{
		j=0;
	  for(;j<MAX_LOW;j++)
	  {
		  m->_map[i][j]=map[i][j];
	  }
	}
}

void StackDPrint(StackD* s)
{
	int i=0;
	assert(s);
	
	if(0==s->size)
	{
		printf("no yuansu!\n");
	  return ;
	}
	for(;i<s->size;i++)
	{
		printf("(%d,%d)-->",(s->array)[i]._x,(s->array)[i]._y);

	}
}

void PrintMaze(Maze*m)
{
    int i=0;
	int j=0;
    assert(m);
	for(;i<MAX_ROW;i++)
	{
		j=0;
	  for(;j<MAX_LOW;j++)
	  {
		  printf("%d ",m->_map[i][j]);
	  }
	  printf("\n");
	}
}



//判断出口
int IsMazeExit(Maze* m,Position cur,Position enter)
{
	if((cur._x==enter._x)&&(cur._y==enter._y))
	{
	 return 0;
	}
	if(0==cur._x||0==cur._y||MAX_ROW-1==cur._x||MAX_LOW-1==cur._y)
	{
	  return 1;
	}
	return 0;
}

//判断入口是否有效
int IsValidEnter(Maze*m,Position enter)
{  
   assert(m);
   if(1==m->_map[enter._x][enter._y])
   {
     return 0;
   }
   return 1;
}



//判断当前这步能否走通
//两个条件  不越界 等于1或者大于之前元素
int _IsPass(Maze * m,Position next,Position cur)
{
  assert(m);
  if(((1==m->_map[next._x][next._y])||((m->_map[cur._x][cur._y])<(m->_map[next._x][next._y])))&&
	  ((next._x<=MAX_ROW-1)&&(next._x>=0)&&(next._y<=MAX_LOW-1)&&(next._y>=0)))
  {
    return 1;
  }
  return 0;
}


//更新栈
 void Saveshortpath(StackD* shortpath,StackD* path)
 {
	 Position ret1;
	 Position ret;

	 int size=0;
	 int i=0;
   assert(shortpath);
   assert(path);
   shortpath->size=0;
   size=path->size;
   while(size)
   {
     StackDPush(shortpath ,path->array[i]);
	 ret= StackDTop(path);
	 ret1= StackDTop(shortpath);

     size--;
	 i++;
   }

 }
//递归体
void  _PassMaze(Maze*m,Position enter,Position cur,StackD* path,StackD*shortpath)
{
	Position next;
	//入口要特殊赋值
	if(!StackDEmpty(path))
	{
	  m->_map[cur._x][cur._y]=2;
	}
	//入栈
	StackDPush(path,cur);
	//情况1:遇到出口 更新栈 并返回
		  if(IsMazeExit(m,cur,enter))
		  {
			//更新栈
			  if(!StackDEmpty(shortpath)||StackDSize(path)<StackDSize(shortpath))
			  {
				  //如果最短路径栈为空,或储存栈比最短路径栈小,则更新小栈
				  Saveshortpath(shortpath,path);
			  }
			  StackDPop(path);
			return;
		  }

    //情况2:向上走通
		  next=cur;
          next._x-=1;
		  //在外面给下一个点赋值(+1)
		 

		  if(_IsPass(m,next,cur))//两个条件  等于1或者大于前一个   不出界
		  {
		    m->_map[next._x][next._y]=m->_map[cur._x][cur._y]+1;
			
			_PassMaze(m,enter,next,path,shortpath);
		  }

      
    //情况3:向左走通
		  next=cur;
          next._y-=1;
		  //在外面给下一个点赋值(+1)
		 

		  if(_IsPass(m,next,cur))//两个条件  等于1或者大于前一个   不出界
		  {
		    m->_map[next._x][next._y]=m->_map[cur._x][cur._y]+1;
			
			_PassMaze(m,enter,next,path,shortpath);
		  }

     
    //情况4:向右走通
		  next=cur;
          next._y+=1;
		 
		 

		  if(_IsPass(m,next,cur))//两个条件  等于1或者大于前一个   不出界
		  {

			//因为必须要先判断是否越界 所以在里面给下一个点赋值(+1)
		    m->_map[next._x][next._y]=m->_map[cur._x][cur._y]+1;
			
			_PassMaze(m,enter,next,path,shortpath);
		  }
    
    //情况5:向下走通
		  next=cur;
          next._x+=1;
		  //在外面给下一个点赋值(+1)
		 

		  if(_IsPass(m,next,cur))//两个条件  等于1或者大于前一个   不出界
		  {
		    m->_map[next._x][next._y]=m->_map[cur._x][cur._y]+1;
			
			_PassMaze(m,enter,next,path,shortpath);
		  }

	//情况6 :走到此处表示走错了  直接出栈此元素
		  StackDPop(path);



}

//递归法
void PassMaze(Maze* m,Position enter,StackD* path,StackD*shortpath)
{
  //判断入口
	if(IsValidEnter(m,enter))
	{
	  return ;
	}
		_PassMaze(m,enter,enter,path,shortpath);
     
}

 

测试文件

#include"LoopMaze.h"

StackD path;
StackD shortpath;
Maze m;

Position ret;

  
void TestLoop()
{
    Position enter;
	

	
	
	enter._x=5;
	enter._y=1;
  StackDInit( &path); 
  StackDInit( &shortpath); 

  InitMaze(&m);
    
  PassMaze(&m, enter,&path,&shortpath);

  PrintMaze(&m);

  StackDPrint( &shortpath);


}
int main ()
{
	TestLoop();
  return 0;
}

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值