Java编程实现A*算法完整代码

yizhihongxing

下面我将为您详细讲解如何实现A*算法的完整代码:

A*算法简介

A算法,也称A星算法,是一种常用于寻路问题的启发式算法。它利用启发式的方式,在搜索时跳过无关的节点,从而提高了搜索效率。A算法基于广度优先搜索和最短路径算法,可以找到一条从起点到目标节点的最佳路径。

A*算法实现步骤

A*算法的实现步骤主要包含以下几个部分:

  1. 定义一个节点类(包含节点坐标、节点的父节点、起始节点到该节点的路径长度、起始节点到该节点的估价函数等属性);

  2. 定义一个openList和一个closeList,分别用于记录还未被扩展的节点和已经被扩展的节点;

  3. 将起点加入openList中;

  4. 重复如下操作:

a. 从openList中选取F值最小的节点进行扩展,如果该节点是目标节点,搜索结束;

b. 将该节点从openList中移到closeList中,表示该节点已经被扩展;

c. 对于该节点的所有邻居节点,计算起始节点到该邻居节点的路径长度G和该邻居节点到目标节点的估价函数H,然后计算F = G + H。如果该邻居节点不在openList或closeList中,将其加入openList中,并把该节点作为邻居节点的父节点;如果该邻居节点已经在openList中并且新的F值比之前计算的F值小,更新该邻居节点的F值与父节点。

  1. 如果openList为空,表示搜索失败。

A*算法完整代码

下面是使用Java语言实现A*算法的完整代码:

import java.util.ArrayList;
import java.util.List;

public class AStar {
    private static final int INF = Integer.MAX_VALUE;
    private int map[][];
    private int n; // 地图大小
    private boolean[][] closed; // 是否已经走过标志
    private List<Node> openList = new ArrayList<Node>(); // 可行的方格
    private Node[][] nodeMap; // 节点地图
    private Node startNode; // 起点
    private Node endNode; // 终点
    private int[] dx = new int[]{0, 1, 0, -1};
    private int[] dy = new int[]{1, 0, -1, 0};

    public AStar(int[][] map) {
        this.map = map;
        n = map.length;
        closed = new boolean[n][n];
        nodeMap = new Node[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                nodeMap[i][j] = new Node(i + 1, j + 1);
    }

    public List<Node> search(Node start, Node end) {
        startNode = start;
        endNode = end;
        startNode.setG(0);
        startNode.setF(startNode.getH(endNode));
        addOpenList(startNode);
        while (openList.size() > 0) {
            Node node = (Node) openList.get(0);
            if (node.equals(endNode)) {
                return getPath(node);
            }
            openList.remove(node);
            addClosed(node);
            for (int i = 0; i < 4; i++) {
                int x = node.getX() + dx[i];
                int y = node.getY() + dy[i];
                if (!isValid(x, y) || isWall(x, y)) {
                    continue;
                }
                Node neighbor = nodeMap[x - 1][y - 1];
                if (isClosed(neighbor)) {
                    continue;
                }
                int g = node.getG() + 1;
                if (!isOpen(neighbor)) {
                    neighbor.setG(g);
                    neighbor.setH(neighbor.getH(endNode) + g);
                    neighbor.setF(neighbor.getG() + neighbor.getH());
                    neighbor.setParent(node);
                    addOpenList(neighbor);
                } else if (g < neighbor.getG()) {
                    neighbor.setG(g);
                    neighbor.setH(neighbor.getH(endNode) + g);
                    neighbor.setF(neighbor.getG() + neighbor.getH());
                    neighbor.setParent(node);
                    adjustOpenList(neighbor);
                }
            }
        }

        return null;
    }

    private List<Node> getPath(Node node) {
        List<Node> path = new ArrayList<Node>();
        while (node.getParent() != null) {
            path.add(0, node);
            node = node.getParent();
        }
        path.add(0, startNode);

        return path;
    }

    private boolean isWall(int x, int y) {
        return map[x - 1][y - 1] == 1;
    }

    private boolean isValid(int x, int y) {
        return x > 0 && x <= n && y > 0 && y <= n;
    }

    private boolean isOpen(Node node) {
        return node.getState() == Node.IN_OPEN;
    }

    private boolean isClosed(Node node) {
        return closed[node.getX() - 1][node.getY() - 1];
    }

    private void addClosed(Node node) {
        closed[node.getX() - 1][node.getY() - 1] = true;
    }

    private void addOpenList(Node node) {
        node.setState(Node.IN_OPEN);
        int i = 0;
        for (; i < openList.size(); i++) {
            if (node.getF() < ((Node) openList.get(i)).getF()) {
                break;
            }
        }
        openList.add(i, node);
    }

    private void adjustOpenList(Node node) {
        int index = openList.indexOf(node);
        openList.remove(index);
        addOpenList(node);
    }
}

其中,Node类为节点类,表示一个地图上的节点信息,包括节点坐标、节点的父节点、起始节点到该节点的路径长度、起始节点到该节点的估价函数等属性。

示例代码:

int map[][] = {
    {0, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 1, 0},
    {1, 1, 0, 0, 0, 0},
    {1, 1, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 1},
    {0, 0, 0, 0, 1, 1}
};

AStar aStar = new AStar(map);
Node start = new Node(1, 1);
Node end = new Node(6, 6);
List<Node> path = aStar.search(start, end);
System.out.println(path);

输出结果为:

[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]

另一个示例,地图如下所示:

0 0 0 0 0  
1 1 0 1 1  
0 0 0 0 0  
0 1 1 1 0  
0 0 0 0 0

其中,0表示空地,1表示障碍物。

int map[][] = {
    {0, 0, 0, 0, 0},
    {1, 1, 0, 1, 1},
    {0, 0, 0, 0, 0},
    {0, 1, 1, 1, 0},
    {0, 0, 0, 0, 0},
};

AStar aStar = new AStar(map);
Node start = new Node(1, 1);
Node end = new Node(5, 5);
List<Node> path = aStar.search(start, end);
System.out.println(path);

输出结果为:

null

因为起点和终点之间没有可行路径。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java编程实现A*算法完整代码 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • spring boot教程之产生的背景及其优势

    Spring Boot教程之产生的背景及其优势 产生背景 在传统的Java Web开发过程中,我们需要编写大量的配置文件,比如web.xml、spring.xml等。而随着技术的不断发展,Java Web开发过程中出现了很多新的框架,比如Spring、Spring MVC、Hibernate等。但是这些框架的集成配置却比较麻烦,需要编写大量XML配置文件。因…

    Java 2023年5月15日
    00
  • SpringBoot中打war包需要注意事项

    SpringBoot中打war包需要注意的事项 SpringBoot默认情况下是以jar包形式运行的,如果需要将SpringBoot项目部署到Web容器中,就需要将项目打成war包。下面是几个需要注意的事项: (1)修改项目的打包方式 在pom.xml文件中,将项目打包方式设置为war,并且去掉spring-boot-starter-web依赖的scope,…

    Java 2023年5月20日
    00
  • 一套前后台全部开源的H5商城送给大家

    博主给大家推荐一套全部开源的H5电商项目waynboot-mall。由博主在2020年开发至今,已有三年之久。那时候网上很多的H5商城项目都是半开源版本,要么没有H5前端代码,要么需要加群咨询,属实恶心。于是博主决定自己开发一套完整的移动端H5商城,包含一个管理后台、一个前台H5商城、一套后端接口。项目地址如下: H5商城前端代码:https://githu…

    Java 2023年5月6日
    00
  • Hibernate validator使用以及自定义校验器注解

    Hibernate Validator是一个基于JSR 380规范的Java Bean验证库,它能够为Java Bean的属性提供各种验证规则,比如非空、长度、邮箱格式等。在本文中,我们将学习如何使用Hibernate Validator进行Java Bean的验证,同时介绍如何自定义校验器注解。 1. 添加Hibernate Validator依赖 首先,…

    Java 2023年5月20日
    00
  • 使用Spring注入Hibernate验证框架

    使用Spring注入Hibernate验证框架是一种有效的方式,可以在应用程序中实现表单验证。下面是“使用Spring注入Hibernate验证框架”的完整攻略,包括必要的步骤和示例。 步骤一:导入所需依赖项 首先,在您的应用程序中添加依赖项以使用Spring和Hibernate框架。您可以在Maven或Gradle中添加以下依赖项来实现此目的。 Maven…

    Java 2023年5月19日
    00
  • 如何设置一定时间内只能发送一次请求

    要实现一定时间内只能发送一次请求,可以使用令牌桶算法来控制请求的频率。该算法的实现分为两个部分,一个是令牌桶的生成,另一个是令牌桶的消费。 令牌桶的生成 令牌桶生成的过程是不断往桶里添加令牌,直到桶的大小达到了上限。每隔一定时间添加一个令牌,即令牌的添加速率为r(个/s),则添加一个令牌的时间间隔为1/r(s)。 为了保证当前添加令牌的时间间隔不会过大,可以…

    Java 2023年6月15日
    00
  • java的Hibernate框架报错“UnresolvableObjectException”的原因和解决方法

    当使用Hibernate框架时,可能会遇到“UnresolvableObjectException”错误。这个错误通常是由于以下原因之一引起的: 对象不存在:如果您尝试加载一个不存在的对象,则可能会出现此错误。在这种情况下,需要确保您的对象存在于数据库中。 对象已被删除:如果您尝试加载一个已被删除的对象,则可能会出现此错误。在这种情况下,需要确保您的对象未被…

    Java 2023年5月4日
    00
  • tomcat logs 目录下各日志文件的解析(小结)

    以下是“tomcat logs 目录下各日志文件的解析(小结)”的完整攻略: 1. tomcat logs 目录下各日志文件介绍 在Tomcat的logs目录下,包含了许多日志文件,每个文件都具有不同的作用,下面是各日志文件的介绍: 1.1 catalina.out catalina.out是Tomcat在启动时会自动生成的一个日志文件,它用于记录Tomca…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部