迷宫求解!
来源:互联网 发布:淘宝怎么搜店铺 编辑:程序博客网 时间:2024/04/29 18:03
问题:从迷宫的入口找到通向出口的路径。
算法:为了描述迷宫的布局,将定义迷宫的数组m[][]设为全局变量以减少形参传递。另外还需要一个结构体来描述迷宫足迹的坐标,定义如下:
struct Maze_Location
{ int x; //行坐标
int y; //列坐标};
int cur_num为记录通道的编号变量,每当有一个可走的通道时,cur_num就加1,最终找到一条路径的时候,该路径的呈现方式是1,2,3,4............依次按编号连成的一条线。刚开始还需设定入口和出门的坐标,并且入口坐标对应的块应该(确切的说是必须)为通道块,因此先将该坐标对应的位置上赋值为1,即cur_num当前的初始编号。为迷宫设定通道块和墙(通道块对应的值是-1,墙为0)程序的大体流程如下:
按(由东---北)的方向寻找路径
{
若下一步是通道块,则
{
编号加1,并且赋值给下一步足迹块;
若此时的这一步的坐标为出口坐标
{直接打印出路径;(一条路径已经找到!)}
否则
{递归调用该算法,但是此时的参数有变化,参数为当前这一步的坐标与当前编号(每次递归的参数都是下一步)}
编号减1;
将该块的值恢复为-1;
}
}
void FindPath(Maze_Location curpos,int cur_num)
{ int i;
Maze_Location next;
Maze_Location direction[4]={{0,1},{-1,0},{0,-1},{1,0}};//改变方向
for (i=0;i<=3;i++)
{
next.x=curpos.x+direction[i].x;
next.y=curpos.y+direction[i].y;
if (m[next.x][next.y]==-1) //若是通道块
{
m[next.x][next.y]=++cur_num; //编号+1
if (next.x!=ending.x || next.y!=ending.y)//下一步的坐标只要不是出口坐标就继续递归
FindPath(next,cur_num);
else
{
print();
printf("\n");
}
m[next.x][next.y]=-1;
cur_num--;
}
}
}
程序如下:
#include "c1.h"#define MAXLENTH 5struct Maze_Location{int x;int y;};typedef int Maze[MAXLENTH][MAXLENTH];Maze m; //创建迷宫m,定义为全局变量减少形参Maze_Location start,ending;//入口坐标、出口坐标int cur_num=1; //初始化序号//子函数开始void print(){ int i,j;for(i=0;i<MAXLENTH;i++){for (j=0;j<MAXLENTH;j++)printf("%3d",m[i][j]);printf("\n");}}void InitMaze(int k){ int i,n,j,x1,y1; for (i=0;i<MAXLENTH;i++) m[0][i]=m[i][0]=m[MAXLENTH-1][i]=m[i][MAXLENTH-1]=0;//四周值为0,0代表墙 printf("请输入你想要布置迷宫除内的墙的个数:\n"); scanf("%d",&n); for (i=1;i<MAXLENTH-1;i++){ for (j=1;j<MAXLENTH-1;j++)m[i][j]=k;//先置迷宫内部全为1,即全是通道}printf("现在开始为迷宫布置墙,请依次输入迷宫内的墙的坐标:(行列均从0开始)\n");for(j=1;j<=n;j++)//布n堵墙{scanf("%d,%d",&x1,&y1);m[x1][y1]=0;}print();//打印迷宫printf("请输入入口坐标:\n");scanf("%d,%d",&start.x,&start.y);printf("请输入出口坐标:\n");scanf("%d,%d",&ending.x,&ending.y);}void FindPath(Maze_Location curpos,int cur_num){ int i;Maze_Location next;Maze_Location direction[4]={{0,1},{-1,0},{0,-1},{1,0}};//注意东就是列加1行不变,而数组中对应的就是Y加1 for (i=0;i<=3;i++) {next.x=curpos.x+direction[i].x;next.y=curpos.y+direction[i].y;if (m[next.x][next.y]==-1){m[next.x][next.y]=++cur_num; if (next.x!=ending.x || next.y!=ending.y) FindPath(next,cur_num);//只要没有到出口就继续寻找else{ print(); printf("\n");} m[next.x][next.y]=-1;//一下两句很重要,若走的块是通道块但却没有其他出路,即只能原路返回,这时 cur_num--; //就要把之前给这个块赋的编号取消,恢复为-1} }}void main(){InitMaze(-1);m[start.x][start.y]=1;printf("迷宫的路径如下:\n");FindPath(start,cur_num);}
此算法很好理解,但有一点不好理解,我想了很久,即如下情形:
0 0 0 0
-1 -1 0 0
0 0 0 0
假设红色部分为现在的足迹,现在开始要往东走,我们大眼一看就知道其实不能往东走,因为下一步尽管是通道块,但是它是个死胡同,没有办法寻找下个路径了,它只能返回原来的路径。但是这在程序里怎么体现呢?这个我想了很久,就是上面的最后两句:
m[next.x][next.y]=-1;
cur_num--;
当足迹有第一个红色-1出走到下一个-1时,首先发现它是通道块,编为它进行编号(假设是序号2),如下:
0 0 0 0
1 2 0 0
0 0 0 0
发现此时的这个-1(序号2)通道除了原方向没有路可走了,那么就要返回,可是如果你直接返回的话那么下次还是会来到这里,这样就陷入死循环了,所以要取消它的编号,让它恢复为普通的通道块,序号同时也减1(用以给别的块赋值)。此时不用担心还会遇见这个死胡同了,因为这时已经到了程序的结尾了,该在红色1处的足迹上进行下一个for循环了,即换方向了。
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解!
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- 迷宫求解
- Windows7启用Administrator用户
- MyEclipse优化1--光标乱跳、卡死、启动加速、自动拼全、检查拼写
- C#简单实现高亮语法编辑器
- jquery日历控件推荐,看看老外们的功底
- MOV PC,LR --ARM汇编
- 迷宫求解!
- Microsoft Help查看器1.0 为帮助内容存储区指定的位置无效或者您无权访错误 的解决办法
- Oracle笔记_基于样例表的更多查询练习
- 这一夜我们只说CreateCompatibleDC
- Quartz 定时器
- RHEL4在VMware虚拟机中扩大linux硬盘空间
- 音乐播放器
- 关于JAVA中split()函数遇到的一点问题
- dc tracking