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 ...
随机推荐
- 三个 AGC D(AGC037D、AGC043D、AGC050D)
大概就 lxr 讲了 4 个 AGC 的 D,有一个以前做过了不算,另外三个都会做罢( 为了避免开三个博客就把它们合并到一起了 AGC 037 D lxr:难度顺序排列大概是 037<043&l ...
- bcftools 提取vcf(snp/indel)文件子集
做群体变异检测后,通常会有提取子集的操作,之前没有发现bcftools有这个功能,都是自己写脚本操作,数据量一上来,速度真的是让人无语凝噎.这里记录下提取子vcf文件的用法,软件版本:bcftools ...
- OOM机制
Linux内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内 ...
- 利用elliipse做相关图
参考资料:<数据探掘 R语言实战> p65-P68 install.packages("rattle") # 获取实验数据集 install.packages(&quo ...
- centos 7的命令变化
1.service -> systemctl命令 2.ifconfig -> ip 命令 3.netstat -> ss命令 4.route -> ip route命令 5.t ...
- C语言中的位段----解析
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位. 例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可. 为了节省存储空间并使处理简便,C语言又提供了一种数据结 ...
- admire, admit
admire 当别人admire你时,小心掉进泥潭(mire).词源:to wonder. wonderful夸人,awful骂人,awesome夸人.admiral与admire词源不同,碰巧长得像 ...
- 大数据学习day34---spark14------1 redis的事务(pipeline)测试 ,2. 利用redis的pipeline实现数据统计的exactlyonce ,3 SparkStreaming中数据写入Hbase实现ExactlyOnce, 4.Spark StandAlone的执行模式,5 spark on yarn
1 redis的事务(pipeline)测试 Redis本身对数据进行操作,单条命令是原子性的,但事务不保证原子性,且没有回滚.事务中任何命令执行失败,其余的命令仍会被执行,将Redis的多个操作放到 ...
- 100个Shell脚本——【脚本8】每日生成一个文件
[脚本8]每日生成一个文件 要求:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑c ...
- c学习 - 第八章:函数
8.7 数组作函数的参数 1.数组元素作函数的参数--值传递,单向传递 2.数组名做函数的参数--地址传送 (1)实参:数组名做实参,传递的是数组首元素的地址 (2)形参:使用同类型的数组名或指针变量 ...