JAVA根据A星算法规划起点到终点二维坐标的最短路径
工具类
AStarUtil.java
import java.util.*; import java.util.stream.Collectors; /** * A星算法工具类 */ public class AStarUtil { private int[][] NODES; public AStarUtil(int[][] NODES) { this.NODES = NODES; } public AStarUtil() { } public static final int STEP = 10; private ArrayList<Node> openList = new ArrayList<Node>(); private ArrayList<Node> closeList = new ArrayList<Node>(); public Node findMinFNodeInOpneList() { Node tempNode = openList.get(0); for (Node node : openList) { if (node.F < tempNode.F) { tempNode = node; } } return tempNode; } public ArrayList<Node> findNeighborNodes(Node currentNode) { ArrayList<Node> arrayList = new ArrayList<Node>(); // 只考虑上下左右,不考虑斜对角 int topX = currentNode.x; int topY = currentNode.y - 1; if (canReach(topX, topY) && !exists(closeList, topX, topY)) { arrayList.add(new Node(topX, topY)); } int bottomX = currentNode.x; int bottomY = currentNode.y + 1; if (canReach(bottomX, bottomY) && !exists(closeList, bottomX, bottomY)) { arrayList.add(new Node(bottomX, bottomY)); } int leftX = currentNode.x - 1; int leftY = currentNode.y; if (canReach(leftX, leftY) && !exists(closeList, leftX, leftY)) { arrayList.add(new Node(leftX, leftY)); } int rightX = currentNode.x + 1; int rightY = currentNode.y; if (canReach(rightX, rightY) && !exists(closeList, rightX, rightY)) { arrayList.add(new Node(rightX, rightY)); } return arrayList; } /** * 可以行走 * * @param x * @param y * @return */ public boolean canReach(int x, int y) { if (x >= 0 && x < NODES.length && y >= 0 && y < NODES[0].length) { return NODES[x][y] == 0; } return false; } /** * 寻找路径 * * @param startNode * @param endNode * @return */ public Node findPath(Node startNode, Node endNode) { // 把起点加入 open list openList.add(startNode); while (openList.size() > 0) { // 遍历 open list ,查找 F值最小的节点,把它作为当前要处理的节点 Node currentNode = findMinFNodeInOpneList(); // 从open list中移除 openList.remove(currentNode); // 把这个节点移到 close list closeList.add(currentNode); ArrayList<Node> neighborNodes = findNeighborNodes(currentNode); for (Node node : neighborNodes) { if (exists(openList, node)) { foundPoint(currentNode, node); } else { notFoundPoint(currentNode, endNode, node); } } if (find(openList, endNode) != null) { return find(openList, endNode); } } return find(openList, endNode); } private void foundPoint(Node tempStart, Node node) { int G = calcG(tempStart, node); if (G < node.G) { node.parent = tempStart; node.G = G; node.calcF(); } } private void notFoundPoint(Node tempStart, Node end, Node node) { node.parent = tempStart; node.G = calcG(tempStart, node); node.H = calcH(end, node); node.calcF(); openList.add(node); } private int calcG(Node start, Node node) { int G = STEP; int parentG = node.parent != null ? node.parent.G : 0; return G + parentG; } private int calcH(Node end, Node node) { int step = Math.abs(node.x - end.x) + Math.abs(node.y - end.y); return step * STEP; } public static Node find(List<Node> nodes, Node point) { for (Node n : nodes) { if ((n.x == point.x) && (n.y == point.y)) { return n; } } return null; } public static boolean exists(List<Node> nodes, Node node) { for (Node n : nodes) { if ((n.x == node.x) && (n.y == node.y)) { return true; } } return false; } public static boolean exists(List<Node> nodes, int x, int y) { for (Node n : nodes) { if ((n.x == x) && (n.y == y)) { return true; } } return false; } public static class Node { public Node(int x, int y) { this.x = x; this.y = y; } public int x; public int y; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int F; public int G; public int H; @Override public String toString() { return "Node{" + "x=" + x + ", y=" + y + '}'; } public void calcF() { this.F = this.G + this.H; } public Node parent; } /** * 根据坐标点获取二维数组 * * @param allNodeList 所有的坐标点 * @param obstaclesNodeList 所有的障碍物的坐标点 * @return */ public static int[][] get2DArrays(List<Node> allNodeList, List<Node> obstaclesNodeList) { int maxX = allNodeList.stream().sorted(Comparator.comparing(Node::getX).reversed()).collect(Collectors.toList()).get(0).x + 1; int maxY = allNodeList.stream().sorted(Comparator.comparing(Node::getY).reversed()).collect(Collectors.toList()).get(0).y + 1; int[][] ints = new int[maxX][maxY]; for (int x = 0; x < maxX; x++) { for (int y = 0; y < maxY; y++) { for (Node o : obstaclesNodeList) { if (o.x == x && o.y == y) { ints[x][y] = 1; break; } else { ints[x][y] = 0; } } } } toStringInts(ints); System.out.println(); return ints; } /** * 规划路径 * * @param startNode 起始点坐标 * @param endNode 要到达的重点坐标 * @return 返回路径的坐标点 为空表示无法到达 */ public List<Node> PlanRoute(Node startNode, Node endNode) { AStarUtil.Node parent = new AStarUtil(NODES).findPath(startNode, endNode); LinkedList<AStarUtil.Node> arrayList = new LinkedList<>(); while (parent != null) { arrayList.addFirst(new AStarUtil.Node(parent.x, parent.y)); parent = parent.parent; } /** * 以下只是为了路线打印出来 无实际作用 */ for (int i = 0; i < NODES.length; i++) { for (int j = 0; j < NODES[0].length; j++) { if (AStarUtil.exists(arrayList, i, j)) { System.out.print("@, "); } else { System.out.print(NODES[i][j] + ", "); } } System.out.println(); } return arrayList; } /** * 打印二维坐标数据 * * @param ints */ public static void toStringInts(int[][] ints) { for (int i = 0; i < ints.length; i++) { for (int j = 0; j < ints[0].length; j++) { System.out.print(ints[i][j] + ", "); } System.out.println(); } } }
使用方法
import java.util.Arrays; import java.util.LinkedList; import java.util.List; /** * * 注:左上角为原点,水平方向是 y轴,垂直方向为 x轴 * * { * { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, ——> y * { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, * { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, * { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, * { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, * { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, * { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, * { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, * { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, * * ∣ * ∨ * x * }; * */ public class AstartMain { public static void main(String[] args) { /** * 模拟所有坐标 */ LinkedList<AStarUtil.Node> nodeLinkedList = new LinkedList<>(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { AStarUtil.Node ori = new AStarUtil.Node(j, i); nodeLinkedList.add(ori); } } /** * 模拟障碍物坐标 */ List<AStarUtil.Node> obstaclesNodeList =new LinkedList<>(); obstaclesNodeList.add(new AStarUtil.Node(3, 3)); obstaclesNodeList.add(new AStarUtil.Node(4, 3)); obstaclesNodeList.add(new AStarUtil.Node(5, 3)); obstaclesNodeList.add(new AStarUtil.Node(1, 4)); obstaclesNodeList.add(new AStarUtil.Node(1, 7)); int[][] arrays = AStarUtil.get2DArrays(nodeLinkedList, obstaclesNodeList); AStarUtil aStarUtil = new AStarUtil(arrays); /** * 起点坐标 */ AStarUtil.Node startNode = new AStarUtil.Node(0, 0); /** * 终点坐标 */ AStarUtil.Node endNode = new AStarUtil.Node(7, 4); /** * 路线的所有二维坐标 */ List<AStarUtil.Node> route = aStarUtil.PlanRoute(startNode, endNode); System.out.println(Arrays.toString(route.toArray())); } }
-----------------------有任何问题可以在评论区评论,也可以私信我,我看到的话会进行回复,欢迎大家指教------------------------
(蓝奏云官网有些地址失效了,需要把请求地址lanzous改成lanzoux才可以)