原文地址:
https://buluo.qq.com/p/detail.html?bid=11148&pid=7659220-1500366685&from=share_copylink
先记录下,以后再慢慢研究=o=
AStar.java
/**
*
*/
package A星算法;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
/**
* <p>Title:AStar </p>
* <p>Description: </p>
* <p>Company: </p>
* @author st5983
* @date 2017年7月19日
*/
public class AStar {
public final static int BAR = 1; // 障碍值
public final static int PATH = 2; // 路径
public final static int DIRECT_VALUE = 10; // 横竖移动代价
public final static int OBLIQUE_VALUE = 14; // 斜移动代价
// OPEN表
Queue<Node> openList = new PriorityQueue<Node>(); // 优先队列(升序)
// CLOSE表
List<Node> closeList = new ArrayList<Node>();
static int[][] maps = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }
};
/**
* 判断结点是否是最终结点
*/
private boolean isEndNode(Coord end,Coord coord)
{ return coord != null && end.equals(coord);
}
/**
* 判断结点能否放入Open列表
*/
private boolean canAddNodeToOpen(MapInfo mapInfo,int x, int y)
{ // 是否在地图中
if (x < 0 || x >= mapInfo.width || y < 0 || y >= mapInfo.hight) return false; // 判断是否是不可通过的结点
if (mapInfo.maps[y][x] == BAR) return false; // 判断结点是否存在close表
if (isCoordInClose(x, y)) return false;
return true;
} /**
* 判断坐标是否在close表中
*/
private boolean isCoordInClose(Coord coord)
{
return coord!=null&&isCoordInClose(coord.x, coord.y);
}
/**
* 判断坐标是否在close表中
*/
private boolean isCoordInClose(int x, int y)
{
if (closeList.isEmpty()) return false;
for (Node node : closeList)
{
if (node.coord.x == x && node.coord.y == y)
{
return true;
}
}
return false;
}
// 计算H值,“曼哈顿” 法,坐标分别取差值相加
private int calcH(Coord end,Coord coord){
return Math.abs(end.x - coord.x) + Math.abs(end.y - coord.y);
}
// 从Open列表中查找结点
private Node findNodeInOpen(Coord coord){
if (coord == null || openList.isEmpty()) return null;
for (Node node : openList){
if (node.coord.equals(coord)){
return node;
}
}
return null;
}
/**
* 6 添加所有邻结点到open表
*/
private void addNeighborNodeInOpen(MapInfo mapInfo,Node current){
int x = current.coord.x;
int y = current.coord.y;// 左
addNeighborNodeInOpen(mapInfo,current, x - 1, y, DIRECT_VALUE); // 上
addNeighborNodeInOpen(mapInfo,current, x, y - 1, DIRECT_VALUE); // 右
addNeighborNodeInOpen(mapInfo,current, x + 1, y, DIRECT_VALUE); // 下
addNeighborNodeInOpen(mapInfo,current, x, y + 1, DIRECT_VALUE); // 左上
addNeighborNodeInOpen(mapInfo,current, x - 1, y - 1, OBLIQUE_VALUE); // 右上
addNeighborNodeInOpen(mapInfo,current, x + 1, y - 1, OBLIQUE_VALUE); // 右下
addNeighborNodeInOpen(mapInfo,current, x + 1, y + 1, OBLIQUE_VALUE); // 左下
addNeighborNodeInOpen(mapInfo,current, x - 1, y + 1, OBLIQUE_VALUE);
}
/**
* 添加一个邻结点到open表
*/
private void addNeighborNodeInOpen(MapInfo mapInfo,Node current, int x, int y, int value){
if (canAddNodeToOpen(mapInfo,x, y)){
Node end=mapInfo.end;
Coord coord = new Coord(x, y);
int G = current.G + value; // 计算邻结点的G值
Node child = findNodeInOpen(coord);
if (child == null){
int H=calcH(end.coord,coord); // 计算H值
if(isEndNode(end.coord,coord)){
child=end;
child.parent=current;
child.G=G;
child.H=H;
}
else{
child = new Node(coord, current, G, H);
}
openList.add(child);
}
else if (child.G > G){
child.G = G;
child.parent = current; // 重新调整堆
openList.add(child);
}
}
}
/**
* (7) 回溯法绘制路径
*/
private void drawPath(int[][] maps, Node end){
if(end==null||maps==null) return;
System.out.println("总代价:" + end.G);
while (end != null){
Coord c = end.coord;
maps[c.y][c.x] = PATH;
end = end.parent;
}
}
/**
* (8) 开始算法,循环移动结点寻找路径,设定循环结束条件,Open表为空或者最终结点在Close表
*/
public void start(MapInfo mapInfo){
if(mapInfo==null) return; // clean
openList.clear();
closeList.clear(); // 开始搜索
System.out.println("开始搜索");
openList.add(mapInfo.start);
moveNodes(mapInfo);
}
/**
* 移动当前结点
*/
private void moveNodes(MapInfo mapInfo){
while (!openList.isEmpty()){
if (isCoordInClose(mapInfo.end.coord)){
drawPath(mapInfo.maps, mapInfo.end);
break;
}
Node current = openList.poll();
closeList.add(current);
addNeighborNodeInOpen(mapInfo,current);
}
}
public static void main(String[] args) {
Node start = new Node(1, 2);
Node end = new Node(5, 5);
int width = 15;
int hight = 7;
MapInfo mapInfo = new MapInfo(maps, width, hight, start, end);
AStar astar = new AStar();
astar.start(mapInfo);
}
}
Coord.java
/**
*
*/
package A星算法;
/**
* <p>Title:Coord </p>
* <p>Description: </p>
* <p>Company: </p>
* @author st5983
* @date 2017年7月19日
*/
public class Coord {
public int x;
public int y;
public Coord(int x, int y) {
this.x = x;
this.y = y;
}
/**
* 重写方法
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof Coord) {
Coord c = (Coord) obj;
return (x == c.x) && (y == c.y);
}
return false;
}
}
MapInfo.java
/**
*
*/
package A星算法;
/**
* <p>Title:MapInfo </p>
* <p>Description: </p>
* <p>Company: </p>
* @author st5983
* @date 2017年7月19日
*/
public class MapInfo {
public int[][] maps; // 二维数组的地图
public int width; // 地图的宽
public int hight; // 地图的高
public Node start; // 起始结点
public Node end; // 最终结点
public MapInfo(int[][] maps, int width, int hight, Node start, Node end) {
this.maps = maps;
this.width = width;
this.hight = hight;
this.start = start;
this.end = end;
}
}
Node.java
/**
*
*/
package A星算法;
/**
* <p>Title:Node </p>
* <p>Description: </p>
* <p>Company: </p>
* @author st5983
* @date 2017年7月19日
*/
public class Node implements Comparable<Node> {
public Coord coord; // 坐标
public Node parent; // 父结点
public int G; // 是个准确的值,是起点到当前结点的代价
public int H; // 是个估值,当前结点到目的结点的估计代价
public Node(int x, int y) {
this.coord = new Coord(x, y);
}
public Node(Coord coord, Node parent, int g, int h) {
this.coord = coord;
this.parent = parent;
G = g;
H = h;
}
@Override
public int compareTo(Node o) {
if (o == null) {
return -1;
}
if ((G + H) > (o.G + o.H)) {
return 1;
} else if ((G + H) < (o.G + o.H)) {
return -1;
}
return 0;
}
}
研究完后再回来写心得====