A星算法原理:
原理我就不再赘述,可以参考这篇博客:https://blog.csdn.net/hitwhylz/article/details/23089415
需要js代码的看这里:https://blog.csdn.net/qq_39687901/article/details/85697127
需要python代码的看这里:https://blog.csdn.net/qq_39687901/article/details/80753433
用法:
这里是八方寻路,如果想改成四方寻路,把AStar中对应的四行搜索代码注释掉就好了。
public class test {
public static void main(String[] arg) {
//创建一个寻路的二维数组,0是可行走区域,非0是障碍
int[][] map2d = new int[10][10];
//设置一些障碍
map2d[4][0]= 1;
map2d[4][1] = 1;
map2d[4][2] = 1;
map2d[4][3] = 1;
map2d[4][4] = 1;
map2d[4][5] = 1;
map2d[4][6] = 1;
//创建A星对象
AStar astar = new AStar(map2d,new Point(0,0),new Point(9,0));
//开始寻路
ArrayList<Point> pointList = astar.start();
//打印寻路结果
for(Point point:pointList){
System.out.println(point.x+","+ point.y);
}
}
}
运行结果:
1,1
2,2
3,3
3,4
3,5
3,6
4,7
5,7
5,6
6,6
7,6
8,6
8,5
9,5
9,4
9,3
9,2
9,1
9,0
源码:
一共3个java文件:AStar.java、Node.java、Point.java
Point.java:
//表示一个二维点
public class Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
//判断两个点是不是相同
public boolean eq(Point p) {
return this.x == p.x && this.y == p.y;
}
}
Node.java:
public class Node implements Comparable<Node>{
public Point point; //节点自己的坐标
public Node father; //父节点
//f=g+h
int g;
int h;
public Node(Point point, Point endPoint, int g) {
this.point = point;
this.g = g;
this.h = (Math.abs(endPoint.x - point.x) + Math.abs(endPoint.y - point.y)) * 10;
}
@Override
public int compareTo(Node o) {
if(o==null) return -1;
if(this.g+this.h>o.g+o.h){
return 1;
}else if(this.g+this.h<o.g+o.h){
return -1;
}else{
return 0;
}
}
}
AStar.java:
package com.mygdx.game.commons.AStar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
public class AStar {
private PriorityQueue<Node> openList = new PriorityQueue<>();
private ArrayList<Node> closeList = new ArrayList<>();
private int[][] map;
private Point startPoint;
private Point endPoint;
private int w;
private int h;
public AStar(int[][] map, Point startPoint, Point endPoint) {
this.map = map;
this.w = map.length;
this.h = map[0].length;
this.startPoint = startPoint;
this.endPoint = endPoint;
}
//判断point是不是在关闭表中
public Node pointInCloseList(Point point) {
for (Node node : this.closeList) {
if (node.point.eq(point)) {
return node;
}
}
return null;
}
//判断point是否在开启表中,如果在就返回它(不取出)
public Node pointInOpenList(Point point) {
for (Node node : this.openList) {
if (node.point.eq(point)) {
return node;
}
}
return null;
}
//搜索周围节点
private void searchNear(Node minNode, int offsetX, int offsetY) {
//越界检测
if (minNode.point.x + offsetX < 0 || minNode.point.x + offsetX >= this.w || minNode.point.y + offsetY < 0 || minNode.point.y + offsetY >= this.h) {
return;
}
//如果是障碍就忽略
if (this.map[minNode.point.x + offsetX][minNode.point.y + offsetY] != 0) {
return;
}
//如果在closelist中就忽略
Point currentPoint = new Point(minNode.point.x + offsetX, minNode.point.y + offsetY);
if (this.pointInCloseList(currentPoint)!=null) {
return;
}
//设置单位花费
int step;
if (offsetX == 0 || offsetY == 0) {
step = 10;
} else {
step = 14;
}
Node currentNode = this.pointInOpenList(currentPoint);
//如果不在openList中,就把它加入openList
if (currentNode == null) {
currentNode = new Node(currentPoint, this.endPoint, minNode.g + step);
currentNode.father = minNode;
this.openList.add(currentNode);
return;
}
//如果在openList中,判断minNode到当前点的G是否更小
if (minNode.g + step < currentNode.g) {
//g值更小,重新计算g值并且改变father
currentNode.g = minNode.g + step;
currentNode.father = minNode;
}
}
public ArrayList<Point> start() {
//寻路结果
ArrayList<Point> pointList = new ArrayList<>();
//如果寻路终点是障碍,就直接中断寻路
if (this.map[this.endPoint.x][this.endPoint.y] == 1) {
return null;
}
//1.把起点放入开启表
Node startNode = new Node(this.startPoint, this.endPoint, 0);
this.openList.add(startNode);
//2.主循环寻路
while (true) {
//从openlist中取出F值最小的节点
Node minNode = this.openList.poll();
//把这个点加入到closeList
this.closeList.add(minNode);
//搜索当前节点周围的节点
this.searchNear(minNode, 0, -1);
this.searchNear(minNode, 0, 1);
this.searchNear(minNode, -1, 0);
this.searchNear(minNode, 1, 0);
this.searchNear(minNode, -1, -1);
this.searchNear(minNode, 1, 1);
this.searchNear(minNode, -1, 1);
this.searchNear(minNode, 1, -1);
//判断是否终止
Node node = this.pointInCloseList(this.endPoint);
if(node!=null){
//终点在关闭表中,说明寻路成功
while(true){
if(node.father!=null){
pointList.add(node.point);
node = node.father;
}else{
Collections.reverse(pointList);
return pointList;
}
}
}
if (this.openList.size() == 0) {
return null;
}
}
}
}