问题分析:
每走一步需要判断周围四个方向是否可以走
假设我们所走的当前位置无处可走,就要进行退栈,退栈之后那么在退栈之后的位置进行判断时不必要再讲刚才走死胡同的那条路径再考虑进来,因此我们引入di
进行记录刚才走过的方向
设计的栈结构体如下
typedef struct
{
int x;
int y;
int di;//假如退栈时记录了上次在该点走过的方向
}Box;
typedef struct
{
Box data[MAX];//存储走过的点
int top;
}
具体代码如下:
//迷宫问题
#include<stdio.h>
#define MAX 30
typedef struct//存储走过路径的下标
{
int x;
int y;
int di;
}Box;
typedef struct//存储路径
{
int top;
Box data[MAX];
}Stack;//不需要再分配空间
int map[10][10]={//存储地图
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
bool search(int beginX,int beginY,int endX,int endY)
{
int i,j,k,di,find;
Stack s;
s.top=-1;//表示刚开始栈空
s.top++;
s.data[s.top].x=beginX;
s.data[s.top].y=beginY; //将起点进栈
s.data[s.top].di=-1;
map[beginX][beginY]=-1;//表示初始点访问过
while(s.top>-1)
{
i=s.data[s.top].x;
j=s.data[s.top].y;
di=s.data[s.top].di;//判断栈顶的点是否是终点
if(i==endX&&j==endY)//如果遇到终点就打印出所有的路径
{
printf("迷宫路径如下:\n");
for(int k=0;k<s.top;k++)
{
if((k+1)%5!=0)
{
printf("(%d,%d)\t",s.data[k].x,s.data[k].y);
}
else
{
printf("\n");
}
}
return true;
}
//找到下步可以行走的路径
find=0;
while(di<4&&find==0)
{
di++;
switch(di)
{
case 0:i=s.data[s.top].x-1;j=s.data[s.top].y;break;
case 1:i=s.data[s.top].x;j=s.data[s.top].y+1;break;
case 2:i=s.data[s.top].x+1;j=s.data[s.top].y;break;
case 3:i=s.data[s.top].x;j=s.data[s.top].y-1;break;
}
if(map[i][j]==0)
{
find=1;
}
}
//当di超过4后会出循环,此时find也是0,如果这样的话就要出栈了
if(find==1)
{
s.data[s.top].di=di;//存储上一步走的方向数一遍退栈后不走之前的路
s.top++;
s.data[s.top].x=i;
s.data[s.top].y=j;
s.data[s.top].di=-1;//下一步从新开始进行查找
map[i][j]=-1;//将走过的赋为-1,进行标记
}
else
{
map[s.data[s.top].x][s.data[s.top].y]=0;
s.top--;//否则出栈
}
}
return false;
}
int main()
{
if(!search(1,1,8,8))
{
printf("没有找到");
}
return 0;
}
第二种做法
使用深度优先遍历进行查找所有的路径
#include<stdio.h>
#include<stdlib.h>
int map[10][10] = { //地图
{ 1,1,1,1,1,1,1,1,1,1 },
{ 1,0,0,1,0,0,0,1,0,1 },
{ 1,0,0,1,0,0,0,1,0,1 },
{ 1,0,0,0,0,1,1,0,0,1 },
{ 1,0,1,1,1,0,0,0,0,1 },
{ 1,0,0,0,1,0,0,0,0,1 },
{ 1,0,1,0,0,0,1,0,0,1 },
{ 1,0,1,1,1,0,1,1,0,1 },
{ 1,1,0,0,0,0,0,0,0,1 },
{ 1,1,1,1,1,1,1,1,1,1 }
};
//i表示下标i,j表示下标j,k表示方向
int fx[5] = { 9,-1,0,1,0 }, fy[5] = { 9,0,1,0,-1 };//表示可以访问的下标范围 9没有用
int steps=1;//设置走过的标志
int check(int i, int j, int k)//检查所走的点是否合理
{
int flag = 1;
if (i + fx[k] <= 0 || i + fx[k] > 8 || j + fx[k] <= 0 || j + fx[k] > 8)//表示不在迷宫内
{
flag= 0;
}
if (map[i + fx[k]][j + fy[k]] != 0)//表示可行
{
flag= 0;
}
return flag;
}
void output()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
printf("%3d", map[i][j]);
}
printf("\n");
}
}
void search(int i, int j)
{
int newi, newj,k;//表示新的下标
for (k = 1; k <= 4; k++)// k=1,2,3,4时(fx[k],fy[k])表示上右下左,四个方向
{
if(check(i,j,k))//如果map[i][j]在迷宫内则进行以下动作
{
newi = i + fx[k];
newj = j + fy[k];//形成新的下标
steps += 1;//将走过的路径行标记
map[newi][newj] = steps;//设置走过的标志
if (newi == 8 && newj == 8)//找到一条路径打印出
{
printf("迷宫如下:\n");
output();
}
else//否则继续深度遍历
{
search(newi, newj);//DFS实现搜索迷宫问题
}
map[newi][newj] = 0;
steps -= 1;
}
}
}
int main()
{
map[1][1] = 1;
search(1, 1);
system("pause");
return 0;
}