工具类

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()));
}
}

JAVA根据A星算法规划起点到终点二维坐标的最短路径的更多相关文章

  1. JAVA版A星算法实现

    import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.u ...

  2. 算法模板——计算几何2(二维凸包——Andrew算法)

    实现功能:求出二维平面内一对散点的凸包(详见Codevs 1298) 很神奇的算法——先将各个点按坐标排序,然后像我们所知的那样一路左转,求出半边的凸包,然后反过来求另一半的凸包 我以前正是因为总抱着 ...

  3. java给图片写正反字体,并将二维码写到图片上,代码实现

    /** * @param filePath * 源图片路径 * @param markContent * 图片中添加内容 * @param outPath * 输出图片路径 字体颜色等在函数内部实现的 ...

  4. 【算法编程 C++ Python】二维数组查找

    题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路: 最简单:每一行都 ...

  5. 标星7000+,这个 Python 艺术二维码生成器厉害了!

    微信二维码,相信大家也并不陌生,为了生成美观的二维码,许多用户都会利用一些二维码生成工具. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手 ...

  6. java 二维数组的行列长度

    在 java 中,其实只有一维数组,而二维数组是在一维数组中嵌套实现的.比如 int[][] a = {{},{},{},{}} 要取行数和某一行的列数可以 : int rowLen = a.leng ...

  7. 题目一:使用Java实现二维数组中的查找

    考点:数组       题目:二维数组中的查找   描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判 ...

  8. java实现二维码的生成和解析:QRCode、zxing 两种方式

    第一种:QRCode.jar,使用QRCode生成和解析二维码 1.导入jar包  2.代码 (1)QRCodeUtil .java import com.swetake.util.Qrcode; i ...

  9. java画海报二维码

    package cn.com.yitong.ares.qrcode; import java.awt.BasicStroke;import java.awt.Color;import java.awt ...

随机推荐

  1. DirectX12 3D 游戏开发与实战第十二章内容

    12.几何着色器 如果不启用曲面细分,那么几何着色器这个可选阶段将会在位于顶点着色器和像素着色器之间.顶点着色器以顶点作为输入数据,而几何着色器以完整的图元为输入数据.与顶点着色器不同的是,顶点着色器 ...

  2. MongoDB 安装/启动/基本操作命令

    1.MongoDB简介 MongoDB是一个基于分布式文件存储的数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系型数据库和非关系数据库之间的 ...

  3. Perl语言编程(大骆驼)

    啰嗦几句 Perl的时代已经过去,现在年轻的同事们基本上都在用Python了.但个人认为单就生物信息文本处理而言,Perl语言是绝对够用的.最主要的是,前辈们搭建的流程大多数是Perl写的,因此,如果 ...

  4. CPU大小端模式及转换

    通信协议中的数据传输.数组的存储方式.数据的强制转换等这些都会牵涉到大小端问题. CPU的大端和小端模式很多地方都会用到,但还是有许多朋友不知道,今天暂且普及一下. 一.为什么会有大小端模式之分呢? ...

  5. Spring Cloud中五花八门的分布式组件我到底该怎么学

    分布式架构的演进 在软件行业,一个应用服务随着功能越来越复杂,用户量越来越大,尤其是互联网行业流量爆发式的增长,导致我们需要不断的重构应用的结构来支撑庞大的用户量,最终从一个简单的系统主键演变成了一个 ...

  6. 『学了就忘』Linux文件系统管理 — 64、磁盘配额的配置步骤

    目录 1.手工建立一个5GB的分区 2.建立需要做限制的三个用户 3.在分区上开启磁盘配额功能 4.建立磁盘配额的配置文件 5.开始设置用户和组的配额限制 6.启动和关闭配额 7.磁盘配额的查询 8. ...

  7. java中类实现Serializable接口的原因

    背景:一个java中的类只有实现了Serializable接口,它的对象才是可序列化的.如果要序列化某些类的对象,这些类就必须实现Serializable接口.Serializable是一个空接口,没 ...

  8. ES6必知,变量的结构赋值。

    对象和数组时 Javascript 中最常用的两种数据结构,由于 JSON 数据格式的普及,二者已经成为 Javascript 语言中特别重要的一部分. 在编码过程中,我们经常定义许多对象和数组,然后 ...

  9. Linux基础命令---ntpq查询时间服务器

    ntpq ntpq指令使用NTP模式6数据包与NTP服务器通信,能够在允许的网络上查询的兼容的服务器.它以交互模式运行,或者通过命令行参数运行. 此命令的适用范围:RedHat.RHEL.Ubuntu ...

  10. OC-copy,单例

    总结 编号 主题 内容 一 NSFileManager NSFileManager介绍/用法(常见的判断)/文件访问/文件操作 二 集合对象的内存管理 集合对象的内存管理/内存管理总结 三 *copy ...