A Star 最短路徑演算法的Java實現
阿新 • • 發佈:2018-11-17
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
執行效果如下
package test.star;
import java.awt.Point;
/** */ /** */
/** */ /**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:描述路徑節點用類
* </p>
* <p>
* Copyright: Copyright (c) 2008
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
public class Node implements Comparable ... {
// 座標
public Point _pos;
// 開始地點數值
public int _costFromStart;
// 目標地點數值
public int _costToObject;
// 父節點
public Node _parentNode;
private Node() ...{
}
/** *//** */
/** *//**
* 以注入座標點方式初始化Node
*
* @param _pos
*/
public Node(Point _pos) ...{
this._pos = _pos;
}
/** *//** */
/** *//**
* 返回路徑成本
*
* @param node
* @return
*/
public int getCost(Node node) ...{
// 獲得座標點間差值 公式:(x1, y1)-(x2, y2)
int m = node._pos.x - _pos.x;
int n = node._pos.y - _pos.y;
// 取兩節點間歐幾理德距離(直線距離)做為估價值,用以獲得成本
return (int) Math.sqrt(m * m + n * n);
}
/** *//** */
/** *//**
* 檢查node物件是否和驗證物件一致
*/
public boolean equals(Object node) ...{
// 驗證座標為判斷依據
if (_pos.x == ((Node) node)._pos.x && _pos.y == ((Node) node)._pos.y) ...{
return true;
}
return false;
}
/** *//** */
/** *//**
* 比較兩點以獲得最小成本物件
*/
public int compareTo(Object node) ...{
int a1 = _costFromStart + _costToObject;
int a2 = ((Node) node)._costFromStart + ((Node) node)._costToObject;
if (a1 < a2) ...{
return -1;
} else if (a1 == a2) ...{
return 0;
} else ...{
return 1;
}
}
/** *//** */
/** *//**
* 獲得上下左右各點間移動限制區域
*
* @return
*/
public LinkedList getLimit() ...{
LinkedList limit = new LinkedList();
int x = _pos.x;
int y = _pos.y;
// 上下左右各點間移動區域(對於斜視地圖,可以開啟註釋的偏移部分,此時將評估8個方位)
// 上
limit.add(new Node(new Point(x, y - 1)));
// 右上
// limit.add(new Node(new Point(x+1, y-1)));
// 右
limit.add(new Node(new Point(x + 1, y)));
// 右下
// limit.add(new Node(new Point(x+1, y+1)));
// 下
limit.add(new Node(new Point(x, y + 1)));
// 左下
// limit.add(new Node(new Point(x-1, y+1)));
// 左
limit.add(new Node(new Point(x - 1, y)));
// 左上
// limit.add(new Node(new Point(x-1, y-1)));
return limit;
}
}
package test.star;
import java.awt.Point;
import java.util.LinkedList;
import java.util.List;
/** */ /** */
/** */ /**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:A*尋徑處理用類(此類為演示用,並不意味著演算法是最佳實現)
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
public class PathFinder ... {
// 路徑優先等級list(此示例中為內部方法)
private LevelList _levelList;
// 已完成路徑的list
private LinkedList _closedList;
// 地圖描述
private int[][] _map;
// 行走區域限制
private int[] _limit;
/** *//** */
/** *//**
* 以注入地圖的2維陣列及限制點描述初始化此類
*
* @param _map
*/
public PathFinder(int[][] map, int[] limit) ...{
_map = map;
_limit = limit;
_levelList = new LevelList();
_closedList = new LinkedList();
}
/** *//** */
/** *//**
* A*方式尋徑,注入開始座標及目標座標後運算,返回可行路徑的List
*
* @param startPos
* @param objectPos
* @return
*/
public List searchPath(Point startPos, Point objectPos) ...{
// 初始化起始節點與目標節點
Node startNode = new Node(startPos);
Node objectNode = new Node(objectPos);
// 設定起始節點引數
startNode._costFromStart = 0;
startNode._costToObject = startNode.getCost(objectNode);
startNode._parentNode = null;
// 加入運算等級序列
_levelList.add(startNode);
// 當運算等級序列中存在資料時,迴圈處理尋徑,直到levelList為空
while (!_levelList.isEmpty()) ...{
// 取出並刪除最初的元素
Node firstNode = (Node) _levelList.removeFirst();
// 判定是否和目標node座標相等
if (firstNode.equals(objectNode)) ...{
// 是的話即可構建出整個行走路線圖,運算完畢
return makePath(firstNode);
} else ...{
// 否則
// 加入已驗證List
_closedList.add(firstNode);
// 獲得firstNode的移動區域
LinkedList _limit = firstNode.getLimit();
// 遍歷
for (int i = 0; i < _limit.size(); i++) ...{
// 獲得相鄰節點
Node neighborNode = (Node) _limit.get(i);
// 獲得是否滿足等級條件
boolean isOpen = _levelList.contains(neighborNode);
// 獲得是否已行走
boolean isClosed = _closedList.contains(neighborNode);
// 判斷是否無法通行
boolean isHit = isHit(neighborNode._pos.x, neighborNode._pos.y);
// 當三則判定皆非時
if (!isOpen && !isClosed && !isHit) ...{
// 設定costFromStart
neighborNode._costFromStart = firstNode._costFromStart + 1;
// 設定costToObject
neighborNode._costToObject = neighborNode.getCost(objectNode);
// 改變neighborNode父節點
neighborNode._parentNode = firstNode;
// 加入level
_levelList.add(neighborNode);
}
}
}
}
// 清空資料
_levelList.clear();
_closedList.clear();
// 當while無法執行時,將返回null
return null;
}
/** *//** */
/** *//**
* 判定是否為可通行區域
*
* @param x
* @param y
* @return
*/