最近在用javafx尝试做一款简单的2D游戏,涉及到自动寻路问题,经过搜索后发现A*算法可用性高。因为没有扎实的算法基础,就用了简单的曼哈顿函数做为F来实现A*算法。实现了通过修改代码来设置障碍。
基本步骤按照百度百科中的伪代码来实现:
原文地址:https://baike.baidu.com/item/A%2A%E7%AE%97%E6%B3%95/215793?fr=aladdin
while(OPEN!=NULL)
{
从OPEN表中取f(n)最小的节点n;
if(n节点==目标节点)
break;
for(当前节点n的每个子节点X)
{
计算f(X);
if(XinOPEN)
if(新的f(X)<OPEN中的f(X))
{
把n设置为X的父亲;
更新OPEN表中的f(n);
}
if(XinCLOSE)
continue;
if(Xnotinboth)
{
把n设置为X的父亲;
求f(X);
并将X插入OPEN表中;//还没有排序
}
}//endfor
将n节点插入CLOSE表中;
按照f(n)将OPEN表中的节点排序;//实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
}//endwhile(OPEN!=NULL)
然后把伪代码中的步骤一个个具体实现。
最后用java实现出来的东西
long begin = System.currentTimeMillis();
mainControl.openList.add(mainControl.startPoint);
while(!mainControl.openList.isEmpty()) {
/**
* Find the note with the min F in the open list
*/
starShape minFpoint = null;
for(starShape ss : mainControl.openList) {
if(minFpoint == null) {
minFpoint = ss;
continue;
}
if(ss.getStarNote().getF()<minFpoint.getStarNote().getF()) {
minFpoint = ss;
}
}
/**
* Check if it finds the destination successfully
*/
if(minFpoint.getStarNote().getF()==0) break;
/**
* check this note's neighbors
*/
ArrayList<starShape> minsNeighbors = minFpoint.getNeighbor();
for(starShape ss : minsNeighbors) {
int newF = calculateNewF(ss, minFpoint);
if(mainControl.openList.contains(ss)) {
/*
* if new F less than old F
* set this note's sup note as minFpoint
* refresh its F
*/
if(newF < ss.getStarNote().getF()) {
ss.getStarNote().setSup(minFpoint.getStarNote());
ss.getStarNote().G = MahattnUtil.OneStepDistance(ss, minFpoint) + minFpoint.getStarNote().G;
}
}else if(mainControl.closeList.contains(ss)) {
continue;
}else {
/*
* set ss's sup as minFpoint
* calculate F
* put ss into openlist
*/
ss.getStarNote().setSup(minFpoint.getStarNote());
ss.getStarNote().G = MahattnUtil.OneStepDistance(ss, minFpoint) + minFpoint.getStarNote().G;
ss.getStarNote().H = MahattnUtil.MahattnDistance(ss, mainControl.desShape);
mainControl.openList.add(ss);
}
}
mainControl.closeList.add(minFpoint);
mainControl.openList.remove(minFpoint);
}
findRoute(mainControl.desShape);
long end = System.currentTimeMillis();
System.out.println(end - begin +"ms");
每次生成路径的时间大概在10ms-14ms
以下是一些较难思考的东西:
这里每个节点用了一个名为starNote的类来实现,其属性包含了:
protected int x = -1;
protected int y = -1;
public int G = 0;
public int H = -1;
protected String status;
protected boolean avilable = true;
private starNote sup;
public starShape shape;
使用x,y即可确定一个点。
扫描二维码关注公众号,回复:
5783888 查看本文章
计算前将所有节点都用这个类实例化出来,再一个个进行操作即可。
曼哈顿函数计算G,以及直接计算H:
public static int MahattnDistance(starShape s1, starShape s2) {
return Math.abs(s1.getStarNote().getX()/5-s2.getStarNote().getX()/5)+Math.abs(s1.getStarNote().getY()/5-s2.getStarNote().getY()/5);
}
public static int MahattnDistance(starNote s1, starNote s2) {
return Math.abs(s1.getX()/5-s2.getX()/5)+Math.abs(s1.getY()/5-s2.getY()/5);
}
最后附上代码:
https://github.com/kingsmanmikey/Astar_Mahattn