一、迷宫问题
1、打印迷宫。(打印二维数组)
2、简单迷宫,找出其中的通路(①迭代法。②递归法)。
3、多条通路迷宫,找出所有的通路。
4、多条通路和带环通路迷宫,求最短通路。
二、函数代码:
1、打印迷宫地图:
void MazePrint() //打印迷宫
{
size_t i =0,j=0;
for (i = 0; i<N; i++)
{
for (j=0; j<N; j++)
{
printf("%d ",maze[i][j]);
}
printf("\n");
}
printf("\n");
}
2、简单迷宫,找出其中的通路(①迭代法。②递归法)。
①迭代法
int MazeGetPath(Pos entry) //迭代法找迷宫通路
{
Pos cur = entry;
Pos next = cur;
Stack s;
StackInit(&s);
StackPush(&s,cur);
while (StackEmpty(&s))
{
cur = StackTop(&s); //栈顶为当前位置
maze[cur.row][cur.col]=2; //注释掉当前坐标
if (cur.col==N-1) //迷宫出口
{
printf("出口坐标:(%d,%d)\n",cur.row,cur.col);
return 1;
}
next = cur; //next置到当前位置
next.row+=1; //向下试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur;//next置到当前位置
next.row-=1; //向上试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur; //next置到当前位置
next.col+=1; //向右试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur; //next置到当前位置
next.col-=1; //向左试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
StackPop(&s); //遇到死胡同,回溯
}
return 0; //此迷宫没有出口
}
②、递归法
void MazeGetPathR(Pos entry) //递归法解决简单迷宫问题
{
Pos cur = entry;
Pos next = cur;
if (next.col>N-1) //递归结束条件
{
printf("找到出口:%d,%d \n",next.row,next.col);
return;
}
maze[entry.row][entry.col] = 2; //标记当前位置
next = cur;
next.row+=1; //下
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
return;
}
next = cur;
next.col-=1; //左
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
return;
}
next = cur;
next.col+=1; //右
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
return;
}
}
3、多条通路迷宫,找出所有的通路(①迭代法。②递归法)。
①迭代法
void MazeGetPath(Pos entry) //迭代法找迷宫通路
{
Pos cur = entry;
Pos next = cur;
Stack s;
StackInit(&s);
StackPush(&s,cur);
while (StackEmpty(&s))
{
cur = StackTop(&s); //栈顶为当前位置
maze[cur.row][cur.col]=2; //注释掉当前坐标
if (cur.col==N-1) //迷宫出口
{
printf("出口坐标:(%d,%d)\n",cur.row,cur.col);
}
next = cur; //next置到当前位置
next.row+=1; //向下试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur;//next置到当前位置
next.row-=1; //向上试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur; //next置到当前位置
next.col+=1; //向右试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur; //next置到当前位置
next.col-=1; //向左试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
StackPop(&s); //遇到死胡同,回溯
}
}
②递归法
void MazeGetPathR(Pos entry) //递归法解决简单迷宫问题
{
Pos cur = entry;
Pos next = cur;
if (next.col>N-1) //递归结束条件
{
printf("找到出口:%d,%d \n",next.row,next.col);
return;
}
maze[entry.row][entry.col] = 2;
next = cur;
next.row-=1; //上
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
next = cur;
next.row+=1; //下
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
next = cur;
next.col-=1; //左
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
next = cur;
next.col+=1; //右
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
}
4、多条通路和带环通路迷宫,求最短通路。
void MazeGetShortPath(Pos entry,Stack* path) //求取最短路径
{
Pos cur = entry;
Pos next = cur;
if (0==StackEmpty(path)) //入口处
{
maze[next.row][next.col] = 2;
}
else //从入口以后,每次标记的数加一。
{
Pos prev = StackTop(path);
maze[next.row][next.col]=maze[prev.row][prev.col]+1;
}
StackPush(path,next);
if (next.col==N-1)
{
printf("找到出口:%d,%d \n",next.row,next.col);
if(!StackEmpty(&shortPath) || StackSize(path)<StackSize(&shortPath)) //始终保持最短路径在shortPath栈中
{
if(shortPath.data)
free(shortPath.data);
shortPath.data = (DataType *)malloc(sizeof(DataType)*path->top);
memcpy(shortPath.data,path->data,sizeof(DataType)*path->top);
shortPath.top = path->top;
shortPath.end = path->top;
}
}
next = entry;
next.row-=1; //上
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
next = entry;
next.row+=1; //下
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
next = entry;
next.col-=1; //左
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
next = entry;
next.col+=1; //右
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
StackPop(path);
}
三、整体代码及测试结果
1、maze.h
void MazePrint(); //打印迷宫
void MazeGetPath(Pos entry); //迭代寻找迷宫通路
void MazeGetPathR(Pos entry); //递归寻找迷宫通路
Stack shortPath;
void MazeGetShortPath(Pos entry,Stack* path); //求取最短路径
2、maze.c
void MazePrint() //打印迷宫
{
size_t i =0,j=0;
for (i = 0; i<N; i++)
{
for (j=0; j<N; j++)
{
printf("%d ",maze[i][j]);
}
printf("\n");
}
printf("\n");
}
int CheckMazeAssess(Pos pos) //检测该坐标是否可通
{
if (pos.row>=0 && pos.row<N
&& pos.col>=0 && pos.col<N
&& maze[pos.row][pos.col]==1)
{
return 1;
}
return 0;
}
void MazeGetPath(Pos entry) //迭代法找迷宫通路
{
Pos cur = entry;
Pos next = cur;
Stack s;
StackInit(&s);
StackPush(&s,cur);
while (StackEmpty(&s))
{
cur = StackTop(&s); //栈顶为当前位置
maze[cur.row][cur.col]=2; //注释掉当前坐标
if (cur.col==N-1) //迷宫出口
{
printf("出口坐标:(%d,%d)\n",cur.row,cur.col);
//return 1;
}
next = cur; //next置到当前位置
next.row+=1; //向下试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur;//next置到当前位置
next.row-=1; //向上试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur; //next置到当前位置
next.col+=1; //向右试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
next = cur; //next置到当前位置
next.col-=1; //向左试探
if(CheckMazeAssess(next))
{
StackPush(&s,next);
continue;
}
StackPop(&s); //遇到死胡同,回溯
}
return 0; //此迷宫没有出口
}
void MazeGetPathR(Pos entry) //递归法解决简单迷宫问题
{
Pos cur = entry;
Pos next = cur;
if (next.col>N-1) //递归结束条件
{
printf("找到出口:%d,%d \n",next.row,next.col);
return;
}
maze[entry.row][entry.col] = 2;
next = cur;
next.row-=1; //上
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
next = cur;
next.row+=1; //下
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
next = cur;
next.col-=1; //左
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
next = cur;
next.col+=1; //右
if (CheckMazeAssess(next))
{
MazeGetPathR(next); //子问题
}
}
int CheckMazeShortAssess(Pos next,Pos cur) //检测该坐标是否可通
{
if (next.row>=0 && next.row<N
&& next.col>=0 && next.col<N
&& (maze[next.row][next.col]==1 ||
maze[next.row][next.col]>maze[cur.row][cur.col]))
{
return 1;
}
else
{
return 0;
}
}
void MazeGetShortPath(Pos entry,Stack* path) //求取最短路径
{
Pos cur = entry;
Pos next = cur;
if (0==StackEmpty(path)) //入口处
{
maze[next.row][next.col] = 2;
}
else //从入口以后,每次标记的数加一。
{
Pos prev = StackTop(path);
maze[next.row][next.col]=maze[prev.row][prev.col]+1;
}
StackPush(path,next);
if (next.col==N-1)
{
printf("找到出口:%d,%d \n",next.row,next.col);
if(!StackEmpty(&shortPath) || StackSize(path)<StackSize(&shortPath)) //始终保持最短路径在shortPath栈中
{
if(shortPath.data)
free(shortPath.data);
shortPath.data = (DataType *)malloc(sizeof(DataType)*path->top);
memcpy(shortPath.data,path->data,sizeof(DataType)*path->top);
shortPath.top = path->top;
shortPath.end = path->top;
}
}
next = entry;
next.row-=1; //上
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
next = entry;
next.row+=1; //下
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
next = entry;
next.col-=1; //左
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
next = entry;
next.col+=1; //右
if (CheckMazeShortAssess(next,cur))
{
MazeGetShortPath(next,path);
}
StackPop(path);
}
3、test.c
void test()
{
Pos entry = {5,2};
Stack path;
StackInit(&path);
StackInit(&shortPath);
MazePrint();
MazeGetPath(entry); //迭代法
MazeGetPathR(entry); //递归法
MazeGetShortPath(entry,&path);
MazePrint();
while (StackEmpty(&shortPath))
{
printf("%d,%d<-", StackTop(&shortPath).row,StackTop(&shortPath).col);
StackPop(&shortPath);
}
printf("entry\n");
}
四、涉及到栈的相关操作请戳栈的基本操作