数据结构---A星寻路算法

news2024/11/26 7:40:55

A星寻路算法

  • 第一步
  • 第二步
  • 第三步
  • 第四步
  • JAVA实现

用于寻找有效路径的算法。

定义俩个集合
OpenList:可到达的格子
CloseList:已到达的格子

每一个格子都具有F、G、H这3个属性

  1. G:从起点走到当前格子的成本,也就是已经花费了多少步。
  2. H:在不考虑障碍的情况下,从当前格子走到目标格子的距离,也就是离目标还有多远。
  3. F:G和H的综合评估,也就是从起点到达当前格子,再从当前格子到达目标格子的总步数。
  4. 公式如下:F = G + H

在下面例子中,格子的左下方数字是G,右下方是H,左上方是F。

第一步

把起点放入OpenList,也就是刚才所说的可到达格子的集合
在这里插入图片描述
OpenList:Grid(1,2)
CloseList:

第二步

找出OpenList中F值最小的方格作为当前方格
(此时OpenList中只有唯一的方格Grid(1,2),把当前格子移出OpenList,放入CloseList)

在这里插入图片描述

OpenList:
CloseList:Grid(1,2)

第三步

找出当前方格(刚刚检查过的格子)上、下、左、右所有可到达的格子,看它们是否在OpenList或CloseList当中。如果不在,则将它们加入OpenList,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。
在这里插入图片描述
在这里插入图片描述

一个格子的“父节点”代表它的来路,在输出最终路线时会用到

第四步

重复刚才的第2步和第3步,直到找到终点为止

启发式搜索:以估值高低来决定搜索优先次序的方法

JAVA实现

package practice;
import java.util.ArrayList;
import java.util.List;

public class AStar {

    //迷宫地图
    public static final int[][] MAZE = {
            { 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0 }
    };

    /**
     * A星寻路主逻辑
     * @param start  迷宫起点
     * @param end  迷宫终点
     */
    public static Grid aStarSearch(Grid start, Grid end) {
        ArrayList<Grid> openList = new ArrayList<Grid>();
        ArrayList<Grid> closeList = new ArrayList<Grid>();
        //把起点加入 openList
        openList.add(start);
        //主循环,每一轮检查一个当前方格节点
        while (openList.size() > 0) {
            // 在openList中查找 F值最小的节点作为当前方格节点
            Grid currentGrid = findMinGird(openList);
            // 当前方格节点从openList中移除
            openList.remove(currentGrid);
            // 当前方格节点进入 closeList  (表示 已达 )
            closeList.add(currentGrid);
            // 找到currentGrid节点的所有邻近节点
            List<Grid> neighbors = findNeighbors(currentGrid, openList, closeList);
            for (Grid grid : neighbors) {
                //邻近节点不在openList中,标记父亲、G、H、F,并放入openList
                grid.initGrid(currentGrid, end);
                openList.add(grid);//这一些节点 可达
            }
            //如果终点在openList中(可达终点),直接返回终点格子
            for (Grid grid : openList){
                if ((grid.x == end.x) && (grid.y == end.y)) {
                    return grid;
                }
            }
        }
        //openList用尽,仍然找不到终点,说明终点不可到达,返回空
        return null;
    }

    //在openList中遍历所有元素,查找 F值最小的节点
    private static Grid findMinGird(ArrayList<Grid> openList) {
        Grid tempGrid = openList.get(0);
        for (Grid grid : openList) {
            if (grid.f < tempGrid.f) {
                tempGrid = grid;
            }
        }
        return tempGrid;
    }
    /**
     * 找到grid节点的所有邻近节点,存储到ArrayList类型的数组gridList中。
     * @param grid      就是当前节点,找他的左右上下节点
     * @param openList  可到达的格子
     * @param closeList 已到达的格子
     * @return 到达终点最优路径的那个节点(F值的最优)
     */
    private static ArrayList<Grid> findNeighbors(Grid grid, List<Grid> openList, List<Grid> closeList) {
        //用于存放grid的上下左右邻居节点
        ArrayList<Grid> gridList = new ArrayList<Grid>();
        //grid的左面节点
        if (isValidGrid(grid.x, grid.y-1, openList, closeList)) {
            gridList.add(new Grid(grid.x, grid.y - 1));
        }
        //grid的右面节点
        if (isValidGrid(grid.x, grid.y+1, openList, closeList)) {
            gridList.add(new Grid(grid.x, grid.y + 1));
        }
        //grid的上面节点
        if (isValidGrid(grid.x-1, grid.y, openList, closeList)) {
            gridList.add(new Grid(grid.x - 1, grid.y));
        }
        //grid的下面节点
        if (isValidGrid(grid.x+1, grid.y, openList, closeList)) {
            gridList.add(new Grid(grid.x + 1, grid.y));
        }
        return gridList;
    }

    //依据下标x,y来判断节点(x,y)是否实际可达
    private static boolean isValidGrid(int x, int y, List<Grid> openList, List<Grid> closeList) {
        //是否超过边界
        if (x < 0 || x >= MAZE.length || y < 0 || y >= MAZE[0].length) {
            return false;
        }
        //是否有障碍物
        if(MAZE[x][y] == 1){
            return false;
        }
        //是否已经在openList中
        if(containGrid(openList, x, y)){
            return false;
        }
        //是否已经在closeList中
        if(containGrid(closeList, x, y)){
            return false;
        }
        return true;
    }

    //判断List数组中是否有x,y值的节点
    private static boolean containGrid(List<Grid> grids, int x, int y) {
        for (Grid grid : grids) {
            if ((grid.x == x) && (grid.y == y)) {
                return true;
            }
        }
        return false;
    }

    static class Grid {
        public int x;
        public int y;
        public int f;
        public int g;  //从起点走到当前格子的成本,也就是已经花费了多少步。
        public int h;
        public Grid parent;

        public Grid(int x, int y) {
            this.x = x;
            this.y = y;
        }

        /**
         * 将可达的新节点初始化参数值(放入openList数组里面)
         * @param parent  标记当前节点的父节点
         * @param end     标记终点
         *     根据parent节点的g,h,f值更新当前节点的值
         *  g  从起点走到当前格子的成本,也就是已经花费了多少步。g+1
         *  h  在不考虑障碍的情况下,从当前格子走到目标格子的距离,也就是离目标还有多远。
         *  f          f = g + h
         */
        public void initGrid(Grid parent, Grid end){
            this.parent = parent;
            this.g = parent.g + 1;
            this.h = Math.abs(this.x - end.x) + Math.abs(this.y - end.y);
            this.f = this.g + this.h;
        }
    }

    public static void main(String[] args) {
        //设置起点和终点
        Grid startGrid = new Grid(2, 1);
        Grid endGrid = new Grid(2, 5);
        //搜索迷宫终点resultGrid (如果找不到就是null)
        Grid resultGrid = aStarSearch(startGrid, endGrid);
        //回溯迷宫路径
        ArrayList<Grid> path = new ArrayList<Grid>();
        while (resultGrid != null) {
            path.add(new Grid(resultGrid.x, resultGrid.y));
            resultGrid = resultGrid.parent;
        }
        //输出迷宫和路径,路径用星号表示
        for (int i = 0; i < MAZE.length; i++) {
            for (int j = 0; j < MAZE[0].length; j++) {
                if (containGrid(path, i, j)) {
                    System.out.print("*, ");
                } else {
                    System.out.print(MAZE[i][j] + ", ");
                }
            }
            System.out.println();
        }
    }
}  

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生产级部署 Python 脚本,崩溃可自启

今天介绍一个生产级的流程管理工具 PM2&#xff0c;通常我们说到 PM2 的时候&#xff0c;都是在说如何部署 Node.js 程序&#xff0c;但是实际上 PM2 很强大&#xff0c;不仅仅可以用来管理 Node.js&#xff0c;它还可以用来管理 Python、PHP、Ruby、perl 等等。 这里就以 Pyt…

看了下华为工资,我不加班了

周五快下班&#xff0c;我本来是想继续好好上班的。那时候是晚上8点左右&#xff0c;跟我一个华为的朋友聊天&#xff0c;聊完之后&#xff0c;我气得把电脑合上&#xff0c;拿上花了7万巨款买的车钥匙&#xff0c;头也不回的走到电梯口&#xff0c;按下了下楼的电梯按钮。-事情…

项目集成MybatisPlus

目录 1.MyBatisPlus介绍 1.1.为什么需要 1.2.MyBatisPlus简介 1.3.MybatisPlus特点 2.项目集成MybatisPlus 2.1.导入依赖 2.2.创建配置 2.3.代码生成主类GenteratorCode 2.4.Controller&#xff0c;Query模板 2.5.生成代码 2.6最终效果 1.MyBatisPlus介绍 1.1.为什么…

SQL优化篇:如何成为一位写优质SQL语句的绝顶高手

(Structured Query Language)标准结构化查询语言简称SQL&#xff0c;编写SQL语句是每位后端开发日常职责中&#xff0c;接触最多的一项工作&#xff0c;SQL是关系型数据库诞生的产物&#xff0c;无论是什么数据库&#xff0c;MySQL、Oracle、SQL Server、DB2、PgSQL....&#x…

JSP ssh网上商品拍卖系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 JSP ssh网上商品拍卖系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S 模式开发。开发环境为TOMCAT7.0…

个人收款的实现方案

最近出于个人需要折腾了一套微信免签支付的个人系统,下面介绍一下整体的一个实现方案 由于微信本身不提供免签的支付api,因此个人若想要实现免签支付,那么只能通过监听微信收款通知来实现了,因此整个系统的实现部分分为 收款服务端和监听客户端来实现 收款服务端实现 整个…

【nowcoder】笔试强训Day5

目录 一、单选题 二、多选题 三、编程题 3.1统计回文 3.2连续最大和 一、单选题 1.下面的程序 编译运行后&#xff0c;在屏幕上显示的结果是&#xff08;&#xff09; public class Test {public static void main(String args[]) {int x, y;x 5 >> 2;y x >&…

docker入门以及常见的命令

目录 1. 什么是docker 2. docker的核心组件 3. docker的安装 3.1 安装的先决条件 3.2.1 ubuntu安装docker 3.2.2 CentOS安装docker 3.3 配置镜像加速器 4. 镜像常用操作 4.1 搜索镜像 4.2 镜像下载 4.3 查看宿主机中的镜像 4.3 删除镜像 5. 容器常用命令 5.1 运行…

#Z1243. 完美数

一&#xff0c;题目描述 一个数是完美的&#xff0c;仅当它等于它的因数中比它小的所有数之和。 例如&#xff1a;28124714&#xff0c;所以 28 是完美的。 由此我们可以定义一个数的不完美值 F(N)&#xff0c;代表 N和比 N 小的所有 N 的因数之和的差的绝对值。 例如&…

c# 服务

是什么 Microsoft Windows 服务&#xff08;过去称为 NT 服务&#xff09;允许用户创建可在其自身的 Windows 会话中长时间运行的可执行应用程序。 这些服务可在计算机启动时自动启动&#xff0c;可以暂停和重启&#xff0c;并且不显示任何用户界面。 这些功能使服务非常适合在…

metrics-server监控主机资源

使用metrics-server实现主机资源监控获取metrics-server资源清单文件修改metrics-server资源清单文件部署metrics-server资源清单文件验证及授权获取metrics-server资源清单文件 直接使用命令来获取资源清单文件 wget https://github.com/kubernetes-sigs/metrics-server/rele…

车用DCDC双路输出电源模块规格书

产品名称&#xff1a;非隔离稳压双路输出车用电源模块 产品型号&#xff1a;LM36J40W2EH 典型特征值&#xff1a;24V/8V(3A)&5V(2A) u 产品概述 LM36J40W2EH模块电源是一款非隔离型双路输出的开关稳压器。它采用集成IC设计&#xff0c;使用一进两出的接线方式&#xff…

【Html圣诞树】2022年的圣诞节了,祝大家节日快乐。

目录 1. 效果展示2. 源代码1. 效果展示 是最近在互联网上很火的一个效果。 是带有背景音乐的,而且背景音乐支持选择,也支持自定义。 2. 源代码 美丽的圣诞树.html <!DOCTYPE html> <html lang="en"

从零学习 InfiniBand-network架构(十) —— IB协议中全局ID

从零学习 InfiniBand-network架构&#xff08;十&#xff09; —— IB协议中全局ID &#x1f508;声明&#xff1a; &#x1f603;博主主页&#xff1a;王_嘻嘻的CSDN主页 &#x1f511;未经作者允许&#xff0c;禁止转载 &#x1f6a9;本专题部分内容源于《InfiniBand-network…

设备指示灯开关状态识别检测系统 yolov5

设备指示灯开关状态识别检测系统是基于yolo网络深度学习模型&#xff0c;对现场画面进行实时监测识别。自动识别仪表示数或开关状态。我们使用YOLO(你只看一次)算法进行对象检测。YOLO是一个聪明的卷积神经网络(CNN)&#xff0c;用于实时进行目标检测。该算法将单个神经网络应用…

Python中使用zip函数的七重境界

1. 引言 Python中有一些内置函数&#xff0c;可以使我们的代码非常优雅。zip 函数就是其中之一&#xff0c;但是zip 函数的使用对于初学者来说不是很直观&#xff0c;有时容易出错。因此本文将从7个层次来由浅入深地来探讨强大的zip 函数的概念、用法和技巧。 闲话少说&#x…

用HTML写一个2023跨年动画代码(烟花+自定义文字+背景音乐+雪花+倒计时)

*2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 文章目录一、前言二、跨年烟花三、效果展示五、HTML源码一、前言 时光荏苒&#xff0c;白驹过隙。 2022这一年又在忙碌中度过了&#xff0c;过去的一年&#xff0c;我们同努力&#xff0c;我们共欢笑&#xff0c;…

ContentProvider基础知识

ContentProvider基础知识 1.ContentProvider入门 1.简介 不同程序之间的数据交换&#xff0c;不同app之间的数据共享学会如何操作数据学会如何监听数据变化学会URI,URImatcher&#xff0c;ContentUris的如何使用2.基本使用 A应用&#xff0c;使用ContentProvider的子类进行暴漏…

RabbitMQ 第二天 高级 8 RabbitMQ 应用问题

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级8 RabbitMQ 应用问题8.1 消息可靠性保障8.1.1 消息补偿8.2 消息幂等性保障8.2.1 乐观锁机制第二天 高级 8 RabbitMQ 应用问题 8.1 消息可靠性保障 在RabbitMQ的使…

pytorch【线性回归】【逻辑回归】【softmax回归】

文章目录零、前置函数线性相乘均方误差损失函数梯度下降函数数据的生成函数一、线性回归1.手动实现线性回归2.调库实现线性回归1.定义我们线性回归的模型2.定义我们的误差函数3.定义优化方法4.模型的训练5.开始训练6.查看模型的参数7.计算我们模型的当前的均方误差二、逻辑回归…