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

下面我将为您详细讲解如何实现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日

相关文章

  • MySQL示例讲解数据库约束以及表的设计

    “MySQL示例讲解数据库约束以及表的设计”是一篇比较综合性的文章,内容在开始之前应该分章节引出。以下是我根据自己的经验和理解对这个主题进行的完整攻略。 1. 关于数据库约束 “数据库约束”是指在创建数据库表时,针对表内字段相关的行为限制和处理措施。常见的数据库约束有NOT NULL约束、UNIQUE约束、PRIMARY KEY约束、FOREIGN KEY约…

    Java 2023年5月26日
    00
  • C#中Request.Cookies 和 Response.Cookies 的区别分析

    下面是详细的攻略: Request.Cookies 和 Response.Cookies 的区别分析 在C#中,Request.Cookies和Response.Cookies都是用来操作HttpCookie的。但它们分别代表了不同的Http上下文,有着不同的作用。下面我们详细分析一下它们的区别。 Request.Cookies Request.Cookie…

    Java 2023年6月15日
    00
  • Java BigInteger类,BigDecimal类,Date类,DateFormat类及Calendar类用法示例

    Java BigInteger类 1. 概述 BigInteger类是java.math包中提供的用于表示大整数的类,它可以处理比long类型更大范围的整数。在实际开发中,当需要进行高精度计算时,就会用到BigInteger类。 2. 用法示例 示例1:计算阶乘 以下代码实现了计算1000的阶乘,并输出结果。 import java.math.*; publ…

    Java 2023年5月20日
    00
  • jdbc实现宠物商店管理系统

    下面是jdbc实现宠物商店管理系统的完整攻略: 1. 准备工作 在开始之前,需要先做好下面这些准备工作: 安装并配置好Java开发环境 安装并配置好MySQL数据库 下载并导入jdbc驱动包 2. 数据库设计 宠物商店管理系统需要管理宠物、客户和订单等信息,因此需要设计对应的数据库结构。这里简单介绍一下三个关键表的设计: 2.1. pet表 pet表包含了宠…

    Java 2023年6月16日
    00
  • 什么是对象终结器?

    对象终结器(Finalizer)是.NET框架中用于清理未经处理的对象的机制,确保在对象被销毁之前,能够执行一些特定的清理工作,如释放资源、关闭文件等。本文将对对象终结器的使用进行详细讲解,并提供两个示例说明。 对象终结器的使用 要使用对象终结器,需要定义一个名为Finalize的方法。这个方法的语法如下: ~MyClass() { // 清理代码 } 在这…

    Java 2023年5月11日
    00
  • Java两整数相除向上取整的方式详解(Math.ceil())

    Java中两个整数相除可能不是整数,因此需要进行取整。向上取整就是将小数部分向上一位取整到最近的整数。 Math类提供了向上取整方法 ceil()。 方法定义 public static double ceil(double a) 参数 a:需要向上取整的数。 返回值 返回double类型,表示a向上取整的结果。 示例说明 示例1 接下来我们看一个例子:计算…

    Java 2023年5月26日
    00
  • java采用中文方式显示时间的方法

    为了让Java程序中以中文方式显示时间,我们可以采用以下两种方法: 使用java.util.Date和java.text.DateFormat 我们可以用java.util.Date类获取当前的日期和时间,并使用java.text.DateFormat类将日期格式化为中文。下面是一个示例: import java.util.Date; import java…

    Java 2023年5月20日
    00
  • Java对象的四种引用方式实例分析

    Java对象的四种引用方式实例分析 在Java中,对象的引用方式可以分为四种:强引用、软引用、弱引用和虚引用。每种引用方式有其特定的应用场景和特点。下面将详细介绍每一种引用方式以及其使用示例。 强引用 强引用是Java中最常用的引用方式。定义一个对象并将其赋值给一个引用变量时,这个引用变量就是强引用。只要强引用存在,对象就不会被垃圾回收机制回收。 例如:定义…

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