谁能告诉我一种寻径算法呀 ~~多谢 rt 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 精简的A*算法 我曾看过一些有关A*算法的程序,不过写得比较简洁、易懂的还是风云写的A*算法教学实例(风云工作室),但是这个算法并没有进行优化,该程序要用到实际应用中,还会有一定的限制,所以我对该算法进行了改进,并加上更详细的算法说明,使其具有更好的教学作用和实用价值。开始前我先给出A*算法的基本思路:问题:求出2D的迷宫中起始点S到目标点E的最短路径?算法: findpath(){ 把S点加入树根(各点所在的树的高度表示从S点到该点所走过的步数);把S点加入排序队列(按该点到E点的距离排序+走过的步数从小到大排序);1、排序队列sort_queue中距离最小的第一个点出列,并保存入store_queue中2、从出列的点出发,分别向4个(或8个)方向中的一个各走出一步3、并估算第2步所走到位置到目标点的距离,并把该位置加入树,最后把该点按距离从小到大排序后并放入队列中。(由trytile函数实现)。4、如果该点从四个方向上都不能移动,则把该点从store_queue中删除5、回到第一点,直到找到E点则结束从目标点回溯树,直到树根则可以找到最佳路径,并保存在path[]中}/*========================================================================精简的A*算法 作者:添翼虎网址:http://tyhweb.163.net Email:[email protected]本程序参考了风云的最短路径代码(http://member.nease.com/~cloudwu),并加以改进和优化:1、把原来用于存放已处理节点的堆栈改为(store_queue)队列,这样在从sort_queue队列出列时可直接放入store_queue中。2、解除了地图大小的限制(如果有64K内存限制时,地图大小只能是180x180)3、删除了原程序中的一些冗余,见程序中的注释。4、程序继续使用dis_map数组保存各点历史历史最佳距离,也包含了某点是否已经经过的信息,虽然这样做可能会比使用链表多用一些内存,但是在搜索时可以节省不时间。5、程序更具有实用性,可直接或修改后运用于你的程序中,但请你使用该代码后应该返回一些信息给我,如算法的改进或使用于什么程序等。本程序可以用Borland C++或DJGPP编译,并附带有一个数据文件 map.dat,保存有地图的数据,(注:该地图文件格式与风云的原代码的地图格式不一样)-------------------------------------------------------------------------*///#define NDEBUG#include <stdio.h>#include <conio.h>#include <assert.h>#include <stdlib.h>#define tile_num(x,y) ((y)*map_w+(x)) //将 x,y 坐标转换为地图上块的编号#define tile_x(n) ((n)%map_w) //由块编号得出 x,y 坐标#define tile_y(n) ((n)/map_w)#define MAPMAXSIZE 180 //地图面积最大为 180x180,如果没有64K内存限制可以更大#define MAXINT 32767//树结构, 比较特殊, 是从叶节点向根节点反向链接,方便从叶节点找到根节点typedef struct tree_node *TREE;struct tree_node {int h; //节点所在的高度,表示从起始点到该节点所有的步数int tile; //该节点的位置TREE father; //该节点的上一步};//链接结构,用于保存处理过的和没有处理过的结点typedef struct link_node *LINK;struct link_node {TREE node;int f;LINK next;};LINK sort_queue; // 保存没有处理的行走方法的节点LINK store_queue; // 保存已经处理过的节点 (搜索完后释放)unsigned char * map; //地图数据unsigned int * dis_map; //保存搜索路径时,中间目标地最优解int map_w,map_h; //地图宽和高int start_x,start_y,end_x,end_y; //地点,终点坐标// 初始化队列void init_queue(){sort_queue=(LINK)malloc(sizeof(*sort_queue));sort_queue->node=NULL;sort_queue->f=-1;sort_queue->next=(LINK)malloc(sizeof(*sort_queue));sort_queue->next->node=NULL;sort_queue->next->f=MAXINT;sort_queue->next->next=NULL;store_queue=(LINK)malloc(sizeof(*store_queue));store_queue->node=NULL;store_queue->f=-1;store_queue->next=NULL;}// 待处理节点入队列, 依靠对目的地估价距离插入排序void enter_queue(TREE node,int f){LINK p=sort_queue,father,q;while(f>p->f) {father=p;p=p->next;assert(p);}q=(LINK)malloc(sizeof(*q));assert(sort_queue);q->f=f,q->node=node,q->next=p;father->next=q;}// 将离目的地估计最近的方案出队列TREE get_from_queue(){LINK bestchoice=sort_queue->next;LINK next=sort_queue->next->next;sort_queue->next=next;bestchoice->next=store_queue->next;store_queue->next=bestchoice;return bestchoice->node;}// 释放栈顶节点void pop_stack(){LINK s=store_queue->next;assert(s);store_queue->next=store_queue->next->next;free(s->node);free(s);}// 释放申请过的所有节点void freetree(){int i;LINK p;while(store_queue){p=store_queue;free(p->node);store_queue=store_queue->next;free(p);}while (sort_queue) {p=sort_queue;free(p->node);sort_queue=sort_queue->next;free(p);}}// 估价函数,估价 x,y 到目的地的距离,估计值必须保证比实际值小int judge(int x,int y){int distance;distance=abs(end_x-x)+abs(end_y-y);return distance;}// 尝试下一步移动到 x,y 可行否int trytile(int x,int y,TREE father){TREE p=father;int h;if (map[tile_num(x,y)]!=' ') return 1; // 如果 (x,y) 处是障碍,失败//这一步用来判断(x,y)点是否已经加入队列,多余可以删除,因为dis_map已经//保存该点是否已经保存//while (p) {// if (x==tile_x(p->tile) && y==tile_y(p->tile)) return 1; //如果 (x,y) 曾经经过,失败// p=p->father;//}h=father->h+1;if (h>=dis_map[tile_num(x,y)]) return 1; // 如果曾经有更好的方案移动到 (x,y) 失败dis_map[tile_num(x,y)]=h; // 记录这次到 (x,y) 的距离为历史最佳距离// 将这步方案记入待处理队列p=(TREE)malloc(sizeof(*p));p->father=father;p->h=father->h+1;p->tile=tile_num(x,y);enter_queue(p,p->h+judge(x,y));return 0;}// 路径寻找主函数int * findpath(void){TREE root;int i,j;int * path;memset(dis_map,0xff,map_h*map_w*sizeof(*dis_map)); //填充dis_map为0XFF,表示各点未曾经过init_queue();root=(TREE)malloc(sizeof(*root));root->tile=tile_num(start_x,start_y);root->h=0;root->father=NULL;enter_queue(root,judge(start_x,start_y));for (;;) {int x,y,child;TREE p;root=get_from_queue();if (root==NULL) {return NULL;}x=tile_x(root->tile);y=tile_y(root->tile);if (x==end_x && y==end_y) break; // 达到目的地成功返回child=trytile(x,y-1,root); //尝试向上移动child&=trytile(x,y+1,root); //尝试向下移动child&=trytile(x-1,y,root); //尝试向左移动child&=trytile(x+1,y,root); //尝试向右移动//child&=trytile(x+1,y-1,root);//尝试向右上移动//child&=trytile(x+1,y+1,root); //尝试向右下移动//child&=trytile(x-1,y+1,root); //尝试向左下移动//child&=trytile(x-1,y-1,root); //尝试向左上移动if (child!=0)pop_stack(); // 如果四个方向均不能移动,释放这个死节点}// 回溯树,将求出的最佳路径保存在 path[] 中path=(int*)malloc((root->h+2)*sizeof(int));assert(path);for (i=0;root;i++) {path[i]=root->tile;root=root->father;}path[i]=-1;freetree();return path;}void printpath(int *path){int i;if(path==NULL) return ;for (i=0;path[i]>=0;i++) {gotoxy(tile_x(path[i])+1,tile_y(path[i])+1);cprintf(".");}}int readmap(){FILE *f;int i,j;f=fopen("map.dat","r");assert(f);fscanf(f,"%d,%d\n",&map_w,&map_h);map=malloc(map_w*map_h+1);assert(map);for(i=0;i<map_h;i++)fgets(map+tile_num(0,i),map_w+2,f);fclose(f);start_x=-1,end_x=-1;for (i=0;i<map_h;i++)for (j=0;j<map_w;j++) {if (map[tile_num(j,i)]=='s') map[tile_num(j,i)]=' ',start_x=j,start_y=i;if (map[tile_num(j,i)]=='e') map[tile_num(j,i)]=' ',end_x=j,end_y=i;}assert(start_x>=0 && end_x>=0);dis_map=malloc(map_w*map_h*sizeof(*dis_map));assert(dis_map);return 0;}void showmap(){int i,j;clrscr();for (i=0;i<map_h;i++) {gotoxy(1,i+1);for (j=0;j<map_w;j++)if (map[tile_num(j,i)]!=' ') cprintf("O");else cprintf(" ");}gotoxy(start_x+1,start_y+1);cprintf("s");gotoxy(end_x+1,end_y+1);cprintf("e");}int main(){int * path;readmap();showmap();getch();path=findpath();printpath(path);if(dis_map) free(dis_map);if(path) free(path);if(map) free(map);getch();return 0;} Kane_Peng 四种寻路算法并比较 好久没搞这些东西了...想了十分钟才勉强回忆起来...写了三个钟头...好累啊...四种算法是DFS,BFS,Heuristic DFS, Heuristic BFS (A*)用了两张障碍表,一张是典型的迷宫:char Block[SY][SX]={{1,1,1,1,1,1,1,1,1,1,1 },{1,0,1,0,1,0,0,0,0,0,1 },{1,0,1,0,0,0,1,0,1,1,1 },{1,0,0,0,1,0,1,0,0,0,1 },{1,0,1,1,0,0,1,0,0,1,1 },{1,0,1,0,1,1,0,1,0,0,1 },{1,0,0,0,0,0,0,0,1,0,1 },{1,0,1,0,1,0,1,0,1,0,1 },{1,0,0,1,0,0,1,0,1,0,1 },{1,1,1,1,1,1,1,1,1,1,1 }};第二张是删掉一些障碍后的:char Block[SY][SX]={{1,1,1,1,1,1,1,1,1,1,1 },{1,0,1,0,1,0,0,0,0,0,1 },{1,0,1,0,0,0,1,0,1,1,1 },{1,0,0,0,0,0,1,0,0,0,1 },{1,0,0,1,0,0,1,0,0,1,1 },{1,0,1,0,0,1,0,1,0,0,1 },{1,0,0,0,0,0,0,0,1,0,1 },{1,0,1,0,0,0,1,0,1,0,1 },{1,0,0,1,0,0,1,0,0,0,1 },{1,1,1,1,1,1,1,1,1,1,1 }};结果:尝试节点数 合法节点数 步数深度优先 416/133 110/43 19/25广度优先 190/188 48/49 19/15深度+启发 283/39 82/22 19/19广度+启发 189/185 48/49 19/15所以可以看出深度+启发是最好的,效率高路径也挺短。A*第一是不真实二是慢三是空间消耗较大。附:dfs+heu的源程序,bc++ 3.1通过#include <iostream.h>#include <memory.h>#include <stdlib.h>#define SX 11 //宽#define SY 10 //长int dx[4]={0,0,-1,1}; //四种移动方向对x和y坐标的影响int dy[4]={-1,1,0,0};/*char Block[SY][SX]= //障碍表{{ 1,1,1,1,1,1,1,1,1,1,1 },{ 1,0,1,0,1,0,0,0,0,0,1 },{ 1,0,1,0,0,0,1,0,1,1,1 },{ 1,0,0,0,0,0,1,0,0,0,1 },{ 1,0,0,1,0,0,1,0,0,1,1 },{ 1,0,1,0,0,1,0,1,0,0,1 },{ 1,0,0,0,0,0,0,0,1,0,1 },{ 1,0,1,0,0,0,1,0,1,0,1 },{ 1,0,0,1,0,0,1,0,0,0,1 },{ 1,1,1,1,1,1,1,1,1,1,1 }};*/char Block[SY][SX]= //障碍表{{ 1,1,1,1,1,1,1,1,1,1,1 },{ 1,0,1,0,1,0,0,0,0,0,1 },{ 1,0,1,0,0,0,1,0,1,1,1 },{ 1,0,0,0,1,0,1,0,0,0,1 },{ 1,0,1,1,0,0,1,0,0,1,1 },{ 1,0,1,0,1,1,0,1,0,0,1 },{ 1,0,0,0,0,0,0,0,1,0,1 },{ 1,0,1,0,1,0,1,0,1,0,1 },{ 1,0,0,1,0,0,1,0,1,0,1 },{ 1,1,1,1,1,1,1,1,1,1,1 }};int MaxAct=4; //移动方向总数char Table[SY][SX]; //已到过标记int Level=-1; //第几步int LevelComplete=0; //这一步的搜索是否完成int AllComplete=0; //全部搜索是否完成char Act[1000]; //每一步的移动方向,搜索1000步,够了吧?int x=1,y=1; //现在的x和y坐标int TargetX=9,TargetY=8; //目标x和y坐标int sum1=0,sum2=0;void Test( );void Back( );int ActOK( );int GetNextAct( );void main( ){ memset(Act,0,sizeof(Act)); //清零 memset(Table,0,sizeof(Table)); Table[y][x]=1; //做已到过标记 while (!AllComplete) //是否全部搜索完 { Level++;LevelComplete=0; //搜索下一步 while (!LevelComplete) { Act[Level]=GetNextAct( ); //改变移动方向 if (Act[Level]<=MaxAct) sum1++; if (ActOK( )) //移动方向是否合理 { sum2++; Test( ); //测试是否已到目标 LevelComplete=1; //该步搜索完成 } else { if (Act[Level]>MaxAct) //已搜索完所有方向 Back( ); //回上一步 if (Level<0) //全部搜索完仍无结果 LevelComplete=AllComplete=1; //退出 } } }}void Test( ){ if ((x==TargetX)&&(y==TargetY)) //已到目标 { for (int i=0;i<=Level;i++) cout<<(int)Act[i]; //输出结果 cout<<endl; cout<<Level+1<<" "<<sum1<<" "<<sum2<<endl; LevelComplete=AllComplete=1; //完成搜索 }}int ActOK( ){ int tx=x+dx[Act[Level]-1]; //将到点的x坐标 int ty=y+dy[Act[Level]-1]; //将到点的y坐标 if (Act[Level]>MaxAct) //方向错误? return 0; if ((tx>=SX)||(tx<0)) //x坐标出界? return 0; if ((ty>=SY)||(ty<0)) //y坐标出界? return 0; if (Table[ty][tx]==1) //已到过? return 0; if (Block[ty][tx]==1) //有障碍? return 0; x=tx; y=ty; //移动 Table[y][x]=1; //做已到过标记 return 1;}void Back( ){ x-=dx[Act[Level-1]-1]; y-=dy[Act[Level-1]-1]; //退回原来的点 Table[y][x]=0; //清除已到过标记 Act[Level]=0; //清除方向 Level--; //回上一层}int GetNextAct( ) //找到下一个移动方向。这一段程序有些乱,//仔细看!{ int dis[4]; int order[4]; int t=32767; int tt=2; for (int i=0;i<4;i++) dis[i]=abs(x+dx[i]-TargetX)+abs(y+dy[i]-TargetY); for (i=0;i<4;i++) if (dis[i]<t) { order[0]=i+1; t=dis[i]; } if (Act[Level]==0) return order[0]; order[1]=-1; for (i=0;i<4;i++) if ((dis[i]==t)&&(i!=(order[0]-1))) { order[1]=i+1; break; } if (order[1]!=-1) { for (i=0;i<4;i++) if (dis[i]!=t) { order[tt]=i+1; tt++; } } else { for (i=0;i<4;i++) if (dis[i]!=t) { order[tt-1]=i+1; tt++; } } if (Act[Level]==order[0]) return order[1]; if (Act[Level]==order[1]) return order[2]; if (Act[Level]==order[2]) return order[3]; if (Act[Level]==order[3]) return 5;} 不贴了到gameres的算法文档里找一下有好多的大部分都是A* SetEntriesInAcl 函数疑问 TcxLookupComboBox 匹配的问题 REPLACE函数未定义问题 stringgrid中设置颜色 老问题资源文件 求UCC/EAN 128条形码的校验位的算法?(在线等待) windows程序问题 自定义公用函数应在哪里声明??帮帮忙!! 如何把listview与一个数据库表格文件相连 程序接口问题 DBGRID的问题 DELPHI打包
我曾看过一些有关A*算法的程序,不过写得比较简洁、易懂的还是风云写的A*算法教学实例(风云工作室),但是这个算法并没有进行优化,该程序要用到实际应用中,还会有一定的限制,所以我对该算法进行了改进,并加上更详细的算法说明,使其具有更好的教学作用和实用价值。开始前我先给出A*算法的基本思路:
问题:求出2D的迷宫中起始点S到目标点E的最短路径?
算法: findpath()
{
把S点加入树根(各点所在的树的高度表示从S点到该点所走过的步数);
把S点加入排序队列(按该点到E点的距离排序+走过的步数从小到大排序);
1、排序队列sort_queue中距离最小的第一个点出列,并保存入store_queue中
2、从出列的点出发,分别向4个(或8个)方向中的一个各走出一步
3、并估算第2步所走到位置到目标点的距离,并把该位置加入树,
最后把该点按距离从小到大排序后并放入队列中。(由trytile函数实现)。
4、如果该点从四个方向上都不能移动,则把该点从store_queue中删除
5、回到第一点,直到找到E点则结束
从目标点回溯树,直到树根则可以找到最佳路径,并保存在path[]中}/*========================================================================
精简的A*算法 作者:添翼虎
网址:http://tyhweb.163.net Email:[email protected]
本程序参考了风云的最短路径代码(http://member.nease.com/~cloudwu),
并加以改进和优化:
1、把原来用于存放已处理节点的堆栈改为(store_queue)队列,这样在从
sort_queue队列出列时可直接放入store_queue中。
2、解除了地图大小的限制(如果有64K内存限制时,地图大小只能是180x180)
3、删除了原程序中的一些冗余,见程序中的注释。
4、程序继续使用dis_map数组保存各点历史历史最佳距离,也包含了某点是否已经
经过的信息,虽然这样做可能会比使用链表多用一些内存,但是在搜索时可以
节省不时间。
5、程序更具有实用性,可直接或修改后运用于你的程序中,但请你使用该代码后
应该返回一些信息给我,如算法的改进或使用于什么程序等。
本程序可以用Borland C++或DJGPP编译,并附带有一个数据文件 map.dat,
保存有地图的数据,(注:该地图文件格式与风云的原代码的地图格式不一样)
-------------------------------------------------------------------------*/
//#define NDEBUG
#include <stdio.h>
#include <conio.h>
#include <assert.h>
#include <stdlib.h>#define tile_num(x,y) ((y)*map_w+(x)) //将 x,y 坐标转换为地图上块的编号
#define tile_x(n) ((n)%map_w) //由块编号得出 x,y 坐标
#define tile_y(n) ((n)/map_w)#define MAPMAXSIZE 180 //地图面积最大为 180x180,如果没有64K内存限制可以更大
#define MAXINT 32767//树结构, 比较特殊, 是从叶节点向根节点反向链接,方便从叶节点找到根节点
typedef struct tree_node *TREE;struct tree_node {
int h; //节点所在的高度,表示从起始点到该节点所有的步数
int tile; //该节点的位置
TREE father; //该节点的上一步
};//链接结构,用于保存处理过的和没有处理过的结点
typedef struct link_node *LINK;struct link_node {
TREE node;
int f;
LINK next;
};LINK sort_queue; // 保存没有处理的行走方法的节点
LINK store_queue; // 保存已经处理过的节点 (搜索完后释放)unsigned char * map; //地图数据
unsigned int * dis_map; //保存搜索路径时,中间目标地最优解int map_w,map_h; //地图宽和高
int start_x,start_y,end_x,end_y; //地点,终点坐标// 初始化队列
void init_queue()
{
sort_queue=(LINK)malloc(sizeof(*sort_queue));
sort_queue->node=NULL;
sort_queue->f=-1;
sort_queue->next=(LINK)malloc(sizeof(*sort_queue));
sort_queue->next->node=NULL;
sort_queue->next->f=MAXINT;
sort_queue->next->next=NULL;store_queue=(LINK)malloc(sizeof(*store_queue));
store_queue->node=NULL;
store_queue->f=-1;
store_queue->next=NULL;
}// 待处理节点入队列, 依靠对目的地估价距离插入排序
void enter_queue(TREE node,int f)
{
LINK p=sort_queue,father,q;
while(f>p->f) {
father=p;
p=p->next;
assert(p);
}
q=(LINK)malloc(sizeof(*q));
assert(sort_queue);
q->f=f,q->node=node,q->next=p;
father->next=q;
}// 将离目的地估计最近的方案出队列
TREE get_from_queue()
{
LINK bestchoice=sort_queue->next;
LINK next=sort_queue->next->next;
sort_queue->next=next;bestchoice->next=store_queue->next;
store_queue->next=bestchoice;
return bestchoice->node;
}// 释放栈顶节点
void pop_stack()
{
LINK s=store_queue->next;
assert(s);
store_queue->next=store_queue->next->next;
free(s->node);
free(s);
}// 释放申请过的所有节点
void freetree()
{
int i;
LINK p;
while(store_queue){
p=store_queue;
free(p->node);
store_queue=store_queue->next;
free(p);
}
while (sort_queue) {
p=sort_queue;
free(p->node);
sort_queue=sort_queue->next;
free(p);
}
}// 估价函数,估价 x,y 到目的地的距离,估计值必须保证比实际值小
int judge(int x,int y)
{
int distance;
distance=abs(end_x-x)+abs(end_y-y);
return distance;
}// 尝试下一步移动到 x,y 可行否
int trytile(int x,int y,TREE father)
{
TREE p=father;
int h;
if (map[tile_num(x,y)]!=' ') return 1; // 如果 (x,y) 处是障碍,失败
//这一步用来判断(x,y)点是否已经加入队列,多余可以删除,因为dis_map已经
//保存该点是否已经保存
//while (p) {
// if (x==tile_x(p->tile) && y==tile_y(p->tile)) return 1; //如果 (x,y) 曾经经过,失败
// p=p->father;
//}
h=father->h+1;
if (h>=dis_map[tile_num(x,y)]) return 1; // 如果曾经有更好的方案移动到 (x,y) 失败
dis_map[tile_num(x,y)]=h; // 记录这次到 (x,y) 的距离为历史最佳距离// 将这步方案记入待处理队列
p=(TREE)malloc(sizeof(*p));
p->father=father;
p->h=father->h+1;
p->tile=tile_num(x,y);
enter_queue(p,p->h+judge(x,y));
return 0;
}// 路径寻找主函数
int * findpath(void)
{
TREE root;
int i,j;
int * path;
memset(dis_map,0xff,map_h*map_w*sizeof(*dis_map)); //填充dis_map为0XFF,表示各点未曾经过
init_queue();
root=(TREE)malloc(sizeof(*root));
root->tile=tile_num(start_x,start_y);
root->h=0;
root->father=NULL;
enter_queue(root,judge(start_x,start_y));
for (;;) {
int x,y,child;
TREE p;
root=get_from_queue();
if (root==NULL) {
return NULL;
}
x=tile_x(root->tile);
y=tile_y(root->tile);
if (x==end_x && y==end_y) break; // 达到目的地成功返回child=trytile(x,y-1,root); //尝试向上移动
child&=trytile(x,y+1,root); //尝试向下移动
child&=trytile(x-1,y,root); //尝试向左移动
child&=trytile(x+1,y,root); //尝试向右移动
//child&=trytile(x+1,y-1,root);//尝试向右上移动
//child&=trytile(x+1,y+1,root); //尝试向右下移动
//child&=trytile(x-1,y+1,root); //尝试向左下移动
//child&=trytile(x-1,y-1,root); //尝试向左上移动if (child!=0)
pop_stack(); // 如果四个方向均不能移动,释放这个死节点
}// 回溯树,将求出的最佳路径保存在 path[] 中
path=(int*)malloc((root->h+2)*sizeof(int));
assert(path);
for (i=0;root;i++) {
path[i]=root->tile;
root=root->father;
}
path[i]=-1;
freetree();
return path;
}void printpath(int *path)
{
int i;
if(path==NULL) return ;
for (i=0;path[i]>=0;i++) {
gotoxy(tile_x(path[i])+1,tile_y(path[i])+1);
cprintf(".");
}
}int readmap()
{
FILE *f;
int i,j;
f=fopen("map.dat","r");
assert(f);
fscanf(f,"%d,%d\n",&map_w,&map_h);
map=malloc(map_w*map_h+1);
assert(map);
for(i=0;i<map_h;i++)
fgets(map+tile_num(0,i),map_w+2,f);
fclose(f);
start_x=-1,end_x=-1;
for (i=0;i<map_h;i++)
for (j=0;j<map_w;j++) {
if (map[tile_num(j,i)]=='s') map[tile_num(j,i)]=' ',start_x=j,start_y=i;
if (map[tile_num(j,i)]=='e') map[tile_num(j,i)]=' ',end_x=j,end_y=i;
}
assert(start_x>=0 && end_x>=0);
dis_map=malloc(map_w*map_h*sizeof(*dis_map));
assert(dis_map);
return 0;
}void showmap()
{
int i,j;
clrscr();
for (i=0;i<map_h;i++) {
gotoxy(1,i+1);
for (j=0;j<map_w;j++)
if (map[tile_num(j,i)]!=' ') cprintf("O");
else cprintf(" ");
}
gotoxy(start_x+1,start_y+1);
cprintf("s");
gotoxy(end_x+1,end_y+1);
cprintf("e");
}int main()
{
int * path;
readmap();
showmap();
getch();
path=findpath();
printpath(path);
if(dis_map) free(dis_map);
if(path) free(path);
if(map) free(map);
getch();
return 0;
}
Kane_Peng
四种寻路算法并比较
好久没搞这些东西了...想了十分钟才勉强回忆起来...
写了三个钟头...好累啊...
四种算法是DFS,BFS,Heuristic DFS, Heuristic BFS (A*)
用了两张障碍表,一张是典型的迷宫:char Block[SY][SX]=
{{1,1,1,1,1,1,1,1,1,1,1 },
{1,0,1,0,1,0,0,0,0,0,1 },
{1,0,1,0,0,0,1,0,1,1,1 },
{1,0,0,0,1,0,1,0,0,0,1 },
{1,0,1,1,0,0,1,0,0,1,1 },
{1,0,1,0,1,1,0,1,0,0,1 },
{1,0,0,0,0,0,0,0,1,0,1 },
{1,0,1,0,1,0,1,0,1,0,1 },
{1,0,0,1,0,0,1,0,1,0,1 },
{1,1,1,1,1,1,1,1,1,1,1 }};第二张是删掉一些障碍后的:char Block[SY][SX]=
{{1,1,1,1,1,1,1,1,1,1,1 },
{1,0,1,0,1,0,0,0,0,0,1 },
{1,0,1,0,0,0,1,0,1,1,1 },
{1,0,0,0,0,0,1,0,0,0,1 },
{1,0,0,1,0,0,1,0,0,1,1 },
{1,0,1,0,0,1,0,1,0,0,1 },
{1,0,0,0,0,0,0,0,1,0,1 },
{1,0,1,0,0,0,1,0,1,0,1 },
{1,0,0,1,0,0,1,0,0,0,1 },
{1,1,1,1,1,1,1,1,1,1,1 }};结果:
尝试节点数 合法节点数 步数
深度优先 416/133 110/43 19/25
广度优先 190/188 48/49 19/15
深度+启发 283/39 82/22 19/19
广度+启发 189/185 48/49 19/15所以可以看出深度+启发是最好的,效率高路径也挺短。A*第一是不真实二是慢三是空间消耗较大。附:dfs+heu的源程序,bc++ 3.1通过
#include <iostream.h>
#include <memory.h>
#include <stdlib.h>#define SX 11 //宽
#define SY 10 //长int dx[4]={0,0,-1,1}; //四种移动方向对x和y坐标的影响
int dy[4]={-1,1,0,0};/*char Block[SY][SX]= //障碍表
{{ 1,1,1,1,1,1,1,1,1,1,1 },
{ 1,0,1,0,1,0,0,0,0,0,1 },
{ 1,0,1,0,0,0,1,0,1,1,1 },
{ 1,0,0,0,0,0,1,0,0,0,1 },
{ 1,0,0,1,0,0,1,0,0,1,1 },
{ 1,0,1,0,0,1,0,1,0,0,1 },
{ 1,0,0,0,0,0,0,0,1,0,1 },
{ 1,0,1,0,0,0,1,0,1,0,1 },
{ 1,0,0,1,0,0,1,0,0,0,1 },
{ 1,1,1,1,1,1,1,1,1,1,1 }};*/char Block[SY][SX]= //障碍表
{{ 1,1,1,1,1,1,1,1,1,1,1 },
{ 1,0,1,0,1,0,0,0,0,0,1 },
{ 1,0,1,0,0,0,1,0,1,1,1 },
{ 1,0,0,0,1,0,1,0,0,0,1 },
{ 1,0,1,1,0,0,1,0,0,1,1 },
{ 1,0,1,0,1,1,0,1,0,0,1 },
{ 1,0,0,0,0,0,0,0,1,0,1 },
{ 1,0,1,0,1,0,1,0,1,0,1 },
{ 1,0,0,1,0,0,1,0,1,0,1 },
{ 1,1,1,1,1,1,1,1,1,1,1 }};int MaxAct=4; //移动方向总数
char Table[SY][SX]; //已到过标记
int Level=-1; //第几步
int LevelComplete=0; //这一步的搜索是否完成
int AllComplete=0; //全部搜索是否完成
char Act[1000]; //每一步的移动方向,搜索1000步,够了吧?
int x=1,y=1; //现在的x和y坐标
int TargetX=9,TargetY=8; //目标x和y坐标
int sum1=0,sum2=0;void Test( );
void Back( );
int ActOK( );
int GetNextAct( );void main( )
{
memset(Act,0,sizeof(Act)); //清零
memset(Table,0,sizeof(Table));
Table[y][x]=1; //做已到过标记
while (!AllComplete) //是否全部搜索完
{
Level++;LevelComplete=0; //搜索下一步
while (!LevelComplete)
{
Act[Level]=GetNextAct( ); //改变移动方向
if (Act[Level]<=MaxAct)
sum1++;
if (ActOK( )) //移动方向是否合理
{
sum2++;
Test( ); //测试是否已到目标
LevelComplete=1; //该步搜索完成
}
else
{
if (Act[Level]>MaxAct) //已搜索完所有方向
Back( ); //回上一步
if (Level<0) //全部搜索完仍无结果
LevelComplete=AllComplete=1; //退出
}
}
}
}void Test( )
{
if ((x==TargetX)&&(y==TargetY)) //已到目标
{
for (int i=0;i<=Level;i++)
cout<<(int)Act[i]; //输出结果
cout<<endl;
cout<<Level+1<<" "<<sum1<<" "<<sum2<<endl;
LevelComplete=AllComplete=1; //完成搜索
}
}int ActOK( )
{
int tx=x+dx[Act[Level]-1]; //将到点的x坐标
int ty=y+dy[Act[Level]-1]; //将到点的y坐标
if (Act[Level]>MaxAct) //方向错误?
return 0;
if ((tx>=SX)||(tx<0)) //x坐标出界?
return 0;
if ((ty>=SY)||(ty<0)) //y坐标出界?
return 0;
if (Table[ty][tx]==1) //已到过?
return 0;
if (Block[ty][tx]==1) //有障碍?
return 0;
x=tx;
y=ty; //移动
Table[y][x]=1; //做已到过标记
return 1;
}void Back( )
{
x-=dx[Act[Level-1]-1];
y-=dy[Act[Level-1]-1]; //退回原来的点
Table[y][x]=0; //清除已到过标记
Act[Level]=0; //清除方向
Level--; //回上一层
}int GetNextAct( ) //找到下一个移动方向。这一段程序有些乱,
//仔细看!
{
int dis[4];
int order[4];
int t=32767;
int tt=2;
for (int i=0;i<4;i++)
dis[i]=abs(x+dx[i]-TargetX)+abs(y+dy[i]-TargetY);
for (i=0;i<4;i++)
if (dis[i]<t)
{
order[0]=i+1;
t=dis[i];
}
if (Act[Level]==0)
return order[0];
order[1]=-1;
for (i=0;i<4;i++)
if ((dis[i]==t)&&(i!=(order[0]-1)))
{
order[1]=i+1;
break;
}
if (order[1]!=-1)
{
for (i=0;i<4;i++)
if (dis[i]!=t)
{
order[tt]=i+1;
tt++;
}
}
else
{
for (i=0;i<4;i++)
if (dis[i]!=t)
{
order[tt-1]=i+1;
tt++;
}
} if (Act[Level]==order[0])
return order[1];
if (Act[Level]==order[1])
return order[2];
if (Act[Level]==order[2])
return order[3];
if (Act[Level]==order[3])
return 5;
}