快速寻路算法
A. 游戏寻路算法
1.四种算法是DFS,BFS,Heuristic DFS, Heuristic BFS 这是建立在VC基础上的
2.高数和线代是必须的,还牵涉到数分和运筹学的知识
B. 最优寻路/遍历算法
你说的是图的搜索算法,不是树的算法。看你的要求,推荐用贪心算法。
每次从当前的所有下层结点当中选择花费最小的子结点进入,之后也都是。
不过对这些整数问题,贪心未必能够找到最好的路径,真正最好的路径应该是使用动态规划算法的。
找一本计算机竞赛的辅导书吧,上面对动态规划讲的会可以的。另外还有一种什么网络流算法,我一直没学会,你可以试试看,也是找图的最短路径的。
对于给定2结点之间的搜索,你可以用双向广度优先算法,从2个结点同时出发,向路径中间结点搜索最短路径。
C. 寻路算法实现
用Dijkstra算法,我做的给你个参考,下面各点是有距离的(移动力),BIG表示不可通过
#define BIG 32767 //无穷大
int pre[6]={0}; //这是关键!pre数组用于记录每个点的前趋,这样算出最短路径后,就可以递归出路径经过的点
int Distance[6]; //用于记录从起点到达每个点的最短路径长度
int Cost[6][6]={{0,1450,1650,BIG,BIG,BIG}, //有向网的邻接矩阵,这里以6个点为例
{1450,0,BIG,1350,2350,BIG},
{1650,BIG,0,BIG,2550,BIG},
{BIG,1350,BIG,0,BIG,1200},
{BIG,2350,2550,BIG,0,850},
{BIG,BIG,BIG,1200,850,0},
};
//Dijkstra算法函数,求给定点到其余各点的最短路径
//参数:邻接矩阵、顶点数、出发点的下标、结果数组、每个点的前趋
void Dijkstra(int Cost[][6],int n,int v0,int Distance[],int pre[])
{
int s[6];
int mindis,dis;
int i,j,u;
//初始化
for(i=0;i<n;i++) {
Distance[i]=Cost[v0][i];
s[i]=0;
}
s[v0] =1; //标记v0
//在当前还未找到最短路径的顶点中,寻找具有最短距离的顶点
for(i=0;i<n;i++){
if(Distance[i]<BIG) pre[i]=v0;
}
for(i=1;i<n;i++) { //每循环一次,求得一个最短路径
mindis=BIG;
for (j=0;j<n;j++) //求离出发点最近的顶点
if(s[j]==0&&Distance[j]<mindis) {
mindis=Distance [j];
u=j;
}
for(j=0;j<n;j++) //修改递增路径序列(集合)
if(s[j]==0) { //对还未求得最短路径的顶点
//求出由最近的顶点 直达各顶点的距离
dis=Distance[u] +Cost[u][j];
//如果新的路径更短,就替换掉原路径
if(Distance[j]>dis){
Distance[j]=dis;
pre[j]=u;
}
}
s[u]=1; // 标记最短路径已经求得
}
}
用Dijkstra函数算出最短路径后,就可以递归出从给定顶点到各点的最短路径上的每个点了,函数如下(不含终点):
char pathres[100]=""; //保存路径
char *Vertex[6]={"福州","上海","广州","北京","成都","西安"};
//参数:起点、终点
void shpath(int st,int ed) //起点应该为Dijkstra函数中的v0
{
if(pre[ed]!=st){
shpath(st,pre[ed]);
}
strcat(pathres,Vertex[pre[ed]]);
strcat(pathres,"-");
} //最后要在主函数中把终点加到pathres里
D. 星际争霸2的寻路算法思路是怎样的
首先地图整体开始前,会用多层可达矩阵算法,算出路径关键点
2,创建关键节点可达矩阵
3,再每个兵当前位置对关键节点进行路径计算
这样可以最小化资源占用就可以完成路径计算了,高数的离散数学,挺容易解的
E. A* 寻路算法
A*算法
�6�1 启发式搜索
– 在搜索中涉及到三个函数
�6�1 g(n) = 从初始结点到结点n的耗费
�6�1 h(n) = 从结点n到目的结点的耗费评估值,启发函数
�6�1 f(n)=g(n)+h(n) 从起始点到目的点的最佳评估值
– 每次都选择f(n)值最小的结点作为下一个结点,
直到最终达到目的结点
– A*算法的成功很大程度依赖于h(n)函数的构建
�6�1 在各种游戏中广泛应用 Open列表和Closed列表
– Open列表
�6�1 包含我们还没有处理到的结点
�6�1 我们最开始将起始结点放入到Open列表中
– Closed列表
�6�1 包含我们已经处理过的结点
�6�1 在算法启动时,Closed列表为空 A* 算法伪代码初始化OPEN列表
初始化CLOSED列表
创建目的结点;称为node_goal
创建起始结点;称为node_start
将node_start添加到OPEN列表
while OPEN列表非空{
从OPEN列表中取出f(n)值最低的结点n
将结点n添加到CLOSED列表中
if 结点n与node_goal相等then 我们找到了路径,程序返回n
else 生成结点n的每一个后继结点n'
foreach 结点n的后继结点n'{
将n’的父结点设置为n
计算启发式评估函数h(n‘)值,评估从n‘到node_goal的费用
计算g(n‘) = g(n) + 从n’到n的开销
计算f(n') = g(n') + h(n')
if n‘位于OPEN或者CLOSED列表and 现有f(n)较优then丢弃n’ ,处理后继n’
将结点n‘从OPEN和CLOSED中删除
添加结点n‘到OPEN列表
}
}
return failure (我们已经搜索了所有的结点,但是仍然没有找到一条路径)
F. 求绕过多个圆形障碍的寻路算法
一个简单的算法就是穷举
一个点由上下左右四个方向不断向另一个点靠近,
处理三种情况,两点直连,需要一次折线,需要两次折线
G. 即时战略游戏中实用的寻路算法都有哪些,比较如何
即时战略游戏 即时战略(RTS,real-time strategy)游戏是战略游戏的一种,主要以电脑游戏的形式存在,它摒弃了传统电视游戏及棋盘战略游戏中“回合”的概念。取而代之,游戏是“即时”进行的:即,它是连续的而不是回合制的。
H. 梦幻西游自动寻路的寻路算法怎么算
A*寻路算法 A*(A-Star)算法是一种静态路网中求解最短路最有效的方法。
公式表示为: f(n)=g(n)+h(n),
其中f(n) 是节点n从初始点到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n)是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。
如果 估价值>实际值, 搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
估价值与实际值越接近,估价函数取得就越好。
例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。明显优于Dijstra算法的毫无无方向的向四周搜索。
conditions of heuristic
Optimistic (must be less than or equal to the real cost)
As close to the real cost as possible
主要搜索过程:
创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
遍历当前节点的各个节点,将n节点放入CLOSE中,取n节点的子节点X,->算X的估价值->
While(OPEN!=NULL)
{
从OPEN表中取估价值f最小的节点n;
if(n节点==目标节点) break;
else
{
if(X in OPEN) 比较两个X的估价值f //注意是同一个节点的两个不同路径的估价值
if( X的估价值小于OPEN表的估价值 )
更新OPEN表中的估价值; //取最小路径的估价值
if(X in CLOSE) 比较两个X的估价值 //注意是同一个节点的两个不同路径的估价值
if( X的估价值小于CLOSE表的估价值 )
更新CLOSE表中的估价值; 把X节点放入OPEN //取最小路径的估价值
if(X not in both)
求X的估价值;
并将X插入OPEN表中; //还没有排序
}
将n节点插入CLOSE表中;
按照估价值将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
启发式搜索其实有很多的算法,比如:局部择优搜索法、最好优先搜索法等等。当然A*也是。这些算法都使用了启发函数,但在具体的选取最佳搜索节点时的策略不同。象局部择优搜索法,就是在搜索的过程中选取“最佳节点”后舍弃其他的兄弟节点,父亲节点,而一直得搜索下去。这种搜索的结果很明显,由于舍弃了其他的节点,可能也把最好的
节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳并不一定是全局的最佳。最好优先就聪明多了,他在搜索时,便没有舍弃节点(除非该节点是死节点),在每一步的估价
中都把当前的节点和以前的节点的估价值比较得到一个“最佳的节点”。这样可以有效的防止“最佳节点”的丢失。那么A*算法又是一种什么样的算法呢?其实A*算法也是一种最
好优先的算法。只不过要加上一些约束条件罢了。由于在一些问题求解时,我们希望能够求解出状态空间搜索的最短路径,也就是用最快的方法求解问题,A*就是干这种事情的!
我们先下个定义,如果一个估价函数可以找出最短的路径,我们称之为可采纳性。A*算法是一个可采纳的最好优先算法。A*算法的估价函数可表示为:
f'(n) = g'(n) + h'(n)
这里,f'(n)是估价函数,g'(n)是起点到终点的最短路径值,h'(n)是n到目标的最断路经的启发值。由于这个f'(n)其实是无法预先知道的,所以我们用前面的估价函数f(n)做
近似。g(n)代替g'(n),但 g(n)>=g'(n)才可(大多数情况下都是满足的,可以不用考虑),h(n)代替h'(n),但h(n)<=h'(n)才可(这一点特别的重要)。可以证明应用这样的估价
函数是可以找到最短路径的,也就是可采纳的。我们说应用这种估价函数的最好优先算法就是A*算法。哈。你懂了吗?肯定没懂。接着看。
举一个例子,其实广度优先算法就是A*算法的特例。其中g(n)是节点所在的层数,h(n)=0,这种h(n)肯定小于h'(n),所以由前述可知广度优先算法是一种可采纳的。实际也是
。当然它是一种最臭的A*算法。
再说一个问题,就是有关h(n)启发函数的信息性。h(n)的信息性通俗点说其实就是在估计一个节点的值时的约束条件,如果信息越多或约束条件越多则排除的节点就越多,估价函
数越好或说这个算法越好。这就是为什么广度优先算法的那么臭的原因了,谁叫它的h(n)=0,一点启发信息都没有。但在游戏开发中由于实时性的问题,h(n)的信息越多,它的计
算量就越大,耗费的时间就越多。就应该适当的减小h(n)的信息,即减小约束条件。但算法的准确性就差了,这里就有一个平衡的问题。
}
I. 游戏中的常用的寻路算法有哪些
f(n)=g(n)+h(n) 从起始点到目的点的最佳评估值
– 每次都选择f(n)值最小的结点作为下一个结点,
直到最终达到目的结点
– A*算法的成功很大程度依赖于h(n)函数的构建
?;) = g(n? 在各种游戏中广泛应用 Open列表和Closed列表
– Open列表
A*算法
? h(n) = 从结点n到目的结点的耗费评估值,启发函数
?,程序返回n
else 生成结点n的每一个后继结点n;
foreach 结点n的后继结点n;{
将n’的父结点设置为n
计算启发式评估函数h(n‘)值,评估从n‘到node_goal的费用
计算g(n‘) = g(n) + 从n’到n的开销
计算f(n?? 在算法启动时,Closed列表为空 A* 算法伪代码初始化OPEN列表
初始化CLOSED列表
创建目的结点;称为node_goal
创建起始结点;称为node_start
将node_start添加到OPEN列表
while OPEN列表非空{
从OPEN列表中取出f(n)值最低的结点n
将结点n添加到CLOSED列表中
if 结点n与node_goal相等then 我们找到了路径;)
if n‘位于OPEN或者CLOSED列表and 现有f(n)较优then丢弃n’ ;) + h(n?? 包含我们还没有处理到的结点
? g(n) = 从初始结点到结点n的耗费
?? 包含我们已经处理过的结点
,处理后继n’
将结点n‘从OPEN和CLOSED中删除
添加结点n‘到OPEN列表
}
}
return failure (我们已经搜索了所有的结点?? 启发式搜索
– 在搜索中涉及到三个函数
??? 我们最开始将起始结点放入到Open列表中
– Closed列表
?
J. 即时战略游戏中实用的寻路算法都有哪些
Potential Field,它是将地图用一个矩阵来表示,矩阵储存着大小不同的电势(整数)。例如,正电势表示吸引,负电势表示排斥。而游戏中的单位本身是一个负电势,游戏以一个数组储存所有单位的电势和位置。这样,在计算一个单位需要怎么从A点到B点时,我们可以用一个新的矩阵将目的地B点设成正电势,并以不同方式(如圆形、四边形等)辐射开来,离B点越远电势越低,直到0。然后将地图矩阵,目的地矩阵,和所有单位数组的电势相加,得出一个新的、反映当前游戏世界的电势矩阵,然后单位再选择周围所有电势点中的最高电势点去走。不过这里坑很多,因为它本质上是Greedy Algorithm,所以它未必能找出解。然而在某些设定中,例如在没有过于复杂地形,并且需要单位自动不相互覆盖的情况下,Potential Field还是可以完成任务。
Flocking Behavior,在对于一大群单位的寻路,计算量是很大的,而且往往会有很多的重复,这些都是可以避免的。如果单位的移动是利用Steering Behavior来实现的话,那么就可以为其中一个单位,称之为Leader,计算路径(例如用导航网格),然后其他单位按照以下Flocking原则来移动:1. 分离,避开相邻单位2. 一致,和整体的移动方向一致,这里应该是Leader的移动方向3. 聚合,向整体的平均位置靠拢这样的话,就可以降低寻路的计算量,并且得到更加真实的群体单位行进效果。