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()));
}
}
JAVA根据A星算法规划起点到终点二维坐标的最短路径的更多相关文章
- JAVA版A星算法实现
import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.u ...
- 算法模板——计算几何2(二维凸包——Andrew算法)
实现功能:求出二维平面内一对散点的凸包(详见Codevs 1298) 很神奇的算法——先将各个点按坐标排序,然后像我们所知的那样一路左转,求出半边的凸包,然后反过来求另一半的凸包 我以前正是因为总抱着 ...
- java给图片写正反字体,并将二维码写到图片上,代码实现
/** * @param filePath * 源图片路径 * @param markContent * 图片中添加内容 * @param outPath * 输出图片路径 字体颜色等在函数内部实现的 ...
- 【算法编程 C++ Python】二维数组查找
题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路: 最简单:每一行都 ...
- 标星7000+,这个 Python 艺术二维码生成器厉害了!
微信二维码,相信大家也并不陌生,为了生成美观的二维码,许多用户都会利用一些二维码生成工具. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手 ...
- java 二维数组的行列长度
在 java 中,其实只有一维数组,而二维数组是在一维数组中嵌套实现的.比如 int[][] a = {{},{},{},{}} 要取行数和某一行的列数可以 : int rowLen = a.leng ...
- 题目一:使用Java实现二维数组中的查找
考点:数组 题目:二维数组中的查找 描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判 ...
- java实现二维码的生成和解析:QRCode、zxing 两种方式
第一种:QRCode.jar,使用QRCode生成和解析二维码 1.导入jar包 2.代码 (1)QRCodeUtil .java import com.swetake.util.Qrcode; i ...
- java画海报二维码
package cn.com.yitong.ares.qrcode; import java.awt.BasicStroke;import java.awt.Color;import java.awt ...
随机推荐
- BehaviorTree.CPP行为树BT的选择节点(四)
Fallback 该节点家族在其他框架中被称为"选择器Selector"或"优先级Priority". 他们的目的是尝试不同的策略,直到找到可行的策略. 它们具 ...
- 51nod 1709 复杂度分析
51nod 1709 复杂度分析 考虑定义 $ F(x) $ 为 \(x\) 为根的子树所有点与 $ x $ 的深度差(其实就是 $ x $ 到每个子树内点的距离)的 1 的个数和. 注意,$ F(x ...
- Scrapy-Splash的安装和使用
Scrapy-Splash是一个Scrapy中支持JavaScript渲染的工具. Scrapy-Splash的安装分为两部分.一个是Splash服务的安装,具体是通过Docker,安装之后,会启动一 ...
- Spring Cloud中五花八门的分布式组件我到底该怎么学
分布式架构的演进 在软件行业,一个应用服务随着功能越来越复杂,用户量越来越大,尤其是互联网行业流量爆发式的增长,导致我们需要不断的重构应用的结构来支撑庞大的用户量,最终从一个简单的系统主键演变成了一个 ...
- 纯CSS圆环与圆
1. 两个标签的嵌套: <div class="element1"> <div class="child1"></div> ...
- Linux 下使用rtcwake实现定时休眠和唤醒设备
查看是否安装rtcwake whereis rtcwake rtcwake: /usr/sbin/rtcwake /usr/share/man/man8/rtcwake.8.gz 查看rtcwake帮 ...
- MySQL索引及性能优化分析
一.SQL性能下降的原因 查询语句问题,各种连接.子查询 索引失效(单值索引.复合索引) 服务器调优及各个参数设置(缓冲.线程池等) 二.索引 排好序的快速查找数据结构 1. 索引分类 单值索引 一个 ...
- 使用$.ajax方式实现页面异步访问,局部更新的效果
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 二叉搜索树、平衡二叉树、红黑树、B树、B+树
完全二叉树: 空树不是完全二叉树,叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部.如果遇到一个结点,左孩子不为空,右孩子为空:或者左右孩子都为空:则该节点之后的队列中的结点都为叶子 ...
- IIS 发布 WebService 连接DB2数据库报错如下图
环境描述: 系统环境: Windows Server 2012 R2 IIS版本:IIS 6.2 C#环境:.NET Framework 4 DB2版本:9.7.500.702 ...