{0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 1, 0, 1, 0}, {0, 1, 0, 1, 0}, {0, 0, 0, 0, 0}请用ARA*算法找到最短路径 用java实现 写注释
时间: 2023-10-02 16:08:48 浏览: 43
以下是使用ARA*算法找到最短路径的Java代码,附注释:
```java
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Random;
public class ARAStar {
static int[][] maze = {{0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 1, 0, 1, 0}, {0, 1, 0, 1, 0}, {0, 0, 0, 0, 0}}; //迷宫地图
static int[] start = {1, 1}; //起点坐标
static int[] end = {3, 3}; //终点坐标
static double w = 1.5; //初始权重
static double wDelta = 0.5; //权重递减量
static int maxIterations = 100; //最大迭代次数
static Random random = new Random(); //随机数生成器
static int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; //四个方向的移动
//定义节点类
static class Node implements Comparable<Node> {
int[] pos; //节点位置
double g; //起点到该节点的实际距离
double h; //该节点到终点的估计距离
double f; //f = g + w * h,w为权重
//节点构造函数
public Node(int[] pos, double g, double h) {
this.pos = pos;
this.g = g;
this.h = h;
this.f = g + w * h;
}
//比较函数,用于PriorityQueue中的排序
@Override
public int compareTo(Node other) {
return Double.compare(f, other.f);
}
}
//计算两个节点之间的曼哈顿距离
static double manhattanDistance(int[] a, int[] b) {
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
}
//判断一个节点是否在迷宫内且不是障碍物
static boolean isValid(int[] pos) {
int x = pos[0], y = pos[1];
return x >= 0 && x < maze.length && y >= 0 && y < maze[0].length && maze[x][y] == 0;
}
//计算起点到终点的最短路径
static ArrayList<int[]> shortestPath() {
PriorityQueue<Node> open = new PriorityQueue<>(); //开放列表
open.add(new Node(start, 0, manhattanDistance(start, end))); //将起点加入开放列表
ArrayList<int[]> closed = new ArrayList<>(); //关闭列表
Node goal = null; //终点节点
int iterations = 0; //迭代次数
while (!open.isEmpty() && iterations < maxIterations) { //当开放列表不为空且未超过最大迭代次数时
Node current = open.poll(); //取出开放列表中f值最小的节点
if (current.pos[0] == end[0] && current.pos[1] == end[1]) { //如果该节点是终点
goal = current; //将该节点设为终点节点
break; //跳出循环
}
closed.add(current.pos); //将该节点加入关闭列表
for (int[] direction : directions) { //遍历四个方向
int[] newPos = {current.pos[0] + direction[0], current.pos[1] + direction[1]}; //计算新位置
if (!isValid(newPos) || closed.contains(newPos)) { //如果新位置不合法或已在关闭列表中
continue; //跳过该方向
}
double newG = current.g + 1; //计算新的实际距离
double newH = manhattanDistance(newPos, end); //计算新的估计距离
Node neighbor = new Node(newPos, newG, newH); //创建邻居节点
if (!open.contains(neighbor)) { //如果邻居节点不在开放列表中
open.add(neighbor); //将邻居节点加入开放列表
} else { //如果邻居节点已在开放列表中
for (Node n : open) { //遍历开放列表
if (n.equals(neighbor) && neighbor.g < n.g) { //如果找到相同节点且新的实际距离更短
open.remove(n); //移除旧节点
open.add(neighbor); //将新节点加入开放列表
break; //跳出循环
}
}
}
}
iterations++; //迭代次数加1
}
ArrayList<int[]> path = new ArrayList<>(); //最短路径
if (goal != null) { //如果存在终点节点
Node current = goal; //从终点节点开始
while (current != null) { //一直向前直到起点
path.add(current.pos); //将节点加入最短路径
current = null;
for (int[] direction : directions) { //遍历四个方向
int[] newPos = {goal.pos[0] + direction[0], goal.pos[1] + direction[1]}; //计算新位置
if (!isValid(newPos) || closed.contains(newPos)) { //如果新位置不合法或已在关闭列表中
continue; //跳过该方向
}
double newG = goal.g + 1; //计算新的实际距离
double newH = manhattanDistance(newPos, end); //计算新的估计距离
Node neighbor = new Node(newPos, newG, newH); //创建邻居节点
if (open.contains(neighbor)) { //如果邻居节点在开放列表中
for (Node n : open) { //遍历开放列表
if (n.equals(neighbor)) { //如果找到相同节点
current = n; //将相同节点设为当前节点
goal = current; //将相同节点设为新的终点节点
break; //跳出循环
}
}
}
}
}
}
return path; //返回最短路径
}
//计算起点到终点的近似最短路径
static ArrayList<int[]> approximateShortestPath() {
ArrayList<int[]> path = new ArrayList<>(); //近似最短路径
while (w >= 1) { //当权重大于等于1时
ArrayList<int[]> tempPath = shortestPath(); //计算最短路径
if (tempPath.isEmpty()) { //如果不存在路径
break; //跳出循环
}
path = tempPath; //将最短路径设为近似最短路径
w -= wDelta; //减小权重
}
return path; //返回近似最短路径
}
//绘制迷宫和路径
static void draw() {
System.out.println("迷宫地图:");
for (int[] row : maze) {
for (int cell : row) {
if (cell == 0) {
System.out.print(" ");
} else {
System.out.print("██");
}
}
System.out.println();
}
ArrayList<int[]> path = approximateShortestPath(); //计算近似最短路径
System.out.println("近似最短路径:");
for (int[] pos : path) {
maze[pos[0]][pos[1]] = 2; //将路径标记为2
}
for (int[] row : maze) {
for (int cell : row) {
if (cell == 0) {
System.out.print(" ");
} else if (cell == 1) {
System.out.print("██");
} else {
System.out.print("░░");
}
}
System.out.println();
}
}
public static void main(String[] args) {
draw(); //绘制迷宫和路径
}
}
```
这段代码实现了ARA*算法找到最短路径,并用Java语言编写。其中,`maze`表示迷宫地图,0表示可以通过的位置,1表示障碍物;`start`表示起点坐标,`end`表示终点坐标;`w`表示初始权重,`wDelta`表示权重递减量;`maxIterations`表示最大迭代次数;`directions`表示四个方向的移动,上下左右分别为(-1,0),(1,0),(0,-1),(0,1)。
首先定义了一个`Node`类表示节点,包含位置、实际距离、估计距离和f值;然后定义了`manhattanDistance`函数计算曼哈顿距离,`isValid`函数判断一个节点是否合法,`shortestPath`函数计算起点到终点的最短路径,`approximateShortestPath`函数计算起点到终点的近似最短路径,`draw`函数绘制迷宫和路径。
在`shortestPath`函数中,使用了优先队列`open`表示开放列表,每次取出f值最小的节点进行扩展,遍历四个方向,计算新的实际距离和估计距离,如果新的节点不在开放列表中,则将其加入开放列表;如果新的节点已在开放列表中,则比较其实际距离,若新的实际距离更短,则将旧节点替换为新节点。
在`approximateShortestPath`函数中,从初始权重开始,每次计算最短路径,若不存在路径则跳出循环,否则将最短路径设为近似最短路径,并减小权重。
最后,在`draw`函数中,先绘制迷宫地图,然后计算近似最短路径,将路径标记为2,最后输出带有路径的迷宫地图。