本文共总结三个方法:
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;
}