迷宫:1–>通路 非1–>死路
简单迷宫
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
求解:①可以采用循环的方式。需要用到栈,从入口开始,往四个方向走,依次将走过的坐标点–入栈;如果走到“死路”,就出栈;–循环;最后栈中保存的就是出迷宫的路线。
求解:②可以采用递归的方式。每走一步,就把剩下的迷宫看成以下一步为入口的“新迷宫”,将走整个迷宫,化成走一个个“小迷宫”,这就是递归。走到出口,就“一路”返回。
多通路迷宫:通路间(不)带环
0 0 0 0 0 0
0 1 1 1 1 1
0 1 0 0 0 0
0 1 0 0 0 0
0 1 1 1 1 1
0 1 0 0 0 0
求解:还是采用递归的方式:将当前步–入栈,然后向四周走;当四周都不能走时—出栈。
(1)为解决“带环”问题—-找到最短出迷宫路径:在判断下一步可以(下一步的数大于当前的数)走后,就把下一步的数改为当前的数+1;这样在再次进入“环”后,不会在环里一直“转圈”。
(2)解决多通路问题:在找到一条“出路后”,不是直接退出,而是把每一条路都走一遍;所以开始从入口进,最后又会从入口出。
下面是代码:
maze.h
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define ROW 4
#define COL 4
int Maze[ROW][COL];
typedef struct Position
{
int _x;
int _y;
}Position;
typedef struct Stack
{
Position* _pos;
int _top; // 表示有效元素个数 表示栈顶位置
int _capacity; // 底层空间的总大小
}Stack;
void StackInit(Stack* s);
// 入栈
void StackPush(Stack* s, Position pos);
// 出栈
void StackPop(Stack* s);
// 获取栈顶元素
//pPos StackTop(Stack* s);
// 有效元素的个数
int StackSize(Stack* s);
// 检测栈是否为空
int StackEmpty(Stack* s);
//打印栈
void PrintfStack(Stack s);
//清空栈
void clearstack(Stack* s);
///迷宫问题函数
//判断入口是否有效
int IsEnterRight(Position enter);
//判断是否是出口
int IsExit(Position cur,Position enter);
//判断next是否可走
int IsNextPass(Position cur,Position next);
//保存路径
void saveshortpath(Stack* shortpath,Stack* path);
//走迷宫
void passmaze(Position enter); //循环(栈)和递归走迷宫函数
//void passmaze(Position enter,Stack* shortpath); //走复杂迷宫函数
maze.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "maze.h"
////////////////////////////////////////////////////
////////////////////////////////////////////////////
int Maze[ROW][COL]=
{
{0,0,1,0},
{0,1,1,1},
{0,1,0,0},
{0,1,0,0},
};
void StackInit(Stack* s)
{
s->_pos=(Position*)malloc(sizeof(Position)*3);
s->_capacity=3;
s->_top=0;
}
// 入栈
void StackPush(Stack* s,Position pos)
{
Position* tmp;
int newCapacity=s->_capacity*2;
if(NULL==s) //未初始化,退出
return;
if(s->_top==s->_capacity) //如果栈已满,就扩容
{
tmp=(Position*)realloc(s->_pos,newCapacity*sizeof(Position));
if(NULL==tmp)
{
printf("扩容失败\n");
return;
}
s->_pos=tmp;
s->_capacity=newCapacity;
}
s->_pos[s->_top]._x=pos._x;
s->_pos[s->_top]._y=pos._y;
s->_top++;
}
// 出栈
void StackPop(Stack* s)
{
if(NULL==s)
return;
if(0==s->_top)
return;
else
s->_top--;
}
// 获取栈顶元素
Position StackTop(Stack* s)
{
if(NULL==s)
exit(EXIT_FAILURE);
return s->_pos[s->_top-1];
}
// 有效元素的个数
int StackSize(Stack* s)
{
if(NULL==s)
return -1;
return s->_top;
}
// 检测栈是否为空
int StackEmpty(Stack* s)
{
if(NULL==s)
exit(EXIT_FAILURE);
if(0==s->_top)
return 1;
else
return 0;
}
//打印栈
void PrintfStack(Stack s)
{
int i=0;
if(0==s._top)
return;
printf("迷宫出口:");
for (;i<s._top;i++)
{
printf("(%d %d)-->",s._pos[i]._x,s._pos[i]._y);
}
printf("\n");
}
//清空栈
void clearstack(Stack* s)
{
s->_top=0;
}
//判出口
int IsExit(Position cur,Position enter)
{
if((cur._x!=enter._x && cur._y!= enter._y)&&
( 0==cur._x || ROW-1==cur._x ||
0==cur._y || COL-1==cur._y)
) //cur在边界即为出口(cur入口要排除在外)
return 1;
return 0; //cur暂不是出口
}
//判入口是否有效
int IsEnterRight(Position enter)
{
if(0==enter._x || ROW-1==enter._x || 0==enter._y || COL-1==enter._y) //enter在"边界"即为有效
return 1;
return 0;
}
// 对简单迷宫进行求解----只有一条通路,迷宫不带环
//---- 用循环的方式求解简单迷宫问题
#if 0
void passmaze(Position enter)
{
Stack s;
Position cur,next;
StackInit(&s);
if(!IsEnterRight(enter)) //判断入口是否有效
{
printf("enter error!\n");
return;
}
StackPush(&s,enter); //把入口入栈
while (!StackEmpty(&s)) //栈不为空,就继续
{
cur=StackTop(&s);
Maze[cur._x][cur._y]=2;
if(IsExit(cur,enter)) //判断当前位置是否是出口
{
PrintfStack(s);
return;
}
//上
next=cur;
next._x-=1;
if(1==Maze[next._x][next._y])
{
StackPush(&s,next); //next为 1 ,可以走-->入栈
continue;
}
//左
next=cur;
next._y-=1;
if(1==Maze[next._x][next._y])
{
StackPush(&s,next); //next为 1 ,可以走-->入栈
continue;
}
//右
next=cur;
next._y+=1;
if(1==Maze[next._x][next._y])
{
StackPush(&s,next); //next为 1 ,可以走-->入栈
continue;
}
//下
next=cur;
next._x+=1;
if(1==Maze[next._x][next._y])
{
StackPush(&s,next); //next为 1 ,可以走-->入栈
continue;
}
else
{
Maze[cur._x][cur._y]=3;
StackPop(&s); //next这一步走错了,回退到上一步-->出栈
}
}
printf("没有出口!\n");
}
#endif
// 用递归的方式求解简单迷宫问题
#if 1
int _passmaze(Position enter,Position cur)
{
Position next;
if(1==Maze[cur._x][cur._y])
{
Maze[cur._x][cur._y]=2;
if(IsExit(cur,enter)) //判断当前位置是否是出口
return 1;
//上
next=cur;
next._x-=1;
if(_passmaze(enter,next))
return 1;
//左
next=cur;
next._y-=1;
if(_passmaze(enter,next))
return 1;
//右
next=cur;
next._y+=1;
if(_passmaze(enter,next))
return 1;
//下
next=cur;
next._x+=1;
if(_passmaze(enter,next))
return 1;
Maze[cur._x][cur._y]=3;
}
return 0;
}
void passmaze(Position enter)
{
if(!IsEnterRight(enter)) //判断入口是否有效
{
printf("enter error!\n");
return;
}
_passmaze(enter,enter);
}
#endif
//对复杂迷宫进行求解---迷宫中可能有多条通路,多条路径有可能构成环
#if 0
void _passmaze(Position enter,Position cur,Stack* path,Stack* shortpath)
{
Position next;
if(StackEmpty(path))
Maze[cur._x][cur._y]=2;
StackPush(path,cur); //把入口入栈
if(IsExit(cur,enter)) //判断当前位置是否是出口
{
if(StackEmpty(shortpath) || StackSize(path)<StackSize(shortpath))
saveshortpath(shortpath,path);
StackPop(path);
return;
}
//上
next=cur;
next._x-=1;
if(IsNextPass(cur,next))
{
Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
_passmaze(enter,next,path,shortpath);
}
//左
next=cur;
next._y-=1;
if(IsNextPass(cur,next))
{
Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
_passmaze(enter,next,path,shortpath);
}
//右
next=cur;
next._y+=1;
if(IsNextPass(cur,next))
{
Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
_passmaze(enter,next,path,shortpath);
}
//下
next=cur;
next._x+=1;
if(IsNextPass(cur,next))
{
Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
_passmaze(enter,next,path,shortpath);
}
StackPop(path); //next这一步走错了,回退到上一步-->出栈
}
void passmaze(Position enter,Stack* shortpath)
{
Stack path;
if(!IsEnterRight(enter)) //判断入口是否有效
{
printf("enter error!\n");
return;
}
StackInit(&path);
_passmaze(enter,enter,&path,shortpath);
}
//判断next是否可走
int IsNextPass(Position cur,Position next)
{
if((1==Maze[next._x][next._y]) ||
(Maze[cur._x][cur._y]<Maze[next._x][next._y]))
return 1;
return 0;
}
//保存路径
void saveshortpath(Stack* shortpath,Stack* path)
{
int i=0;
assert(path);
if(0==path->_top)
return;
clearstack(shortpath);
for (;i<path->_top;i++)
{
shortpath->_pos=path->_pos;
}
shortpath->_top=i;
}
#endif
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "maze.h"
int main()
{
Position enter;
Stack shortpath;
int i=0,j=0;
StackInit(&shortpath);
enter._x=3;
enter._y=1;
//passmaze(enter,&shortpath);
passmaze(enter);
for (i=0;i<ROW;i++)
{
for (j=0;j<COL;j++)
{
printf("%d ",Maze[i][j]);
}
printf("\n");
}
PrintfStack(shortpath);
return 0;
}