11.A星寻路算法

news/2025/2/13 23:24:42/文章来源:https://www.cnblogs.com/changming06/p/18714587

14.A星寻路算法

题目

迷宫寻路需求,在一个迷宫游戏中,有一些怪物攻击主角,现在希望小怪物,能自动绕过迷宫中的障碍物,寻找到主角的所在。

思路

A星寻路算法(A*search algorithm),是一种用于寻找有效路径的算法。

简单的场景举例(简化问题),看一看A星寻路算法的工作过程。

小怪物从绿色的小方块开始每次只能移动一步,且不能穿越墙壁,求到达红色小方块的最少步数。

引入两个集合和一个公式。

集合:OpenList(可到达的格子),CloseList(已到达的格子)。

公式:F = G + H

每一个格子都具有F,G,H这3个属性,G(从起点走到当前格子的成本,既是从起点走大当前格子,已经走的步数),H(在不考虑障碍物的情况下,从当前格子走到目标格子的距离,也就是离目标还有多远),F(G和H之和,既是从起点到达当前格子,再从当前格子到达目标格子的总步数)。

第一步,把起点放入OpenList,也就是刚才所说的可到达格子的集合。第2步,找出OpenList中F值最小的方格作为当前方格。虽然我们没有直接计算 起点方格的F值,但此时OpenList中只有唯一的方格Grid(1,2),把当前格子移出 OpenList,放入CloseList。代表这个格子已到达并检查过了。第3步,找出当前方格(刚刚检查过的格子)上、下、左、右所有可到达的格 子,看它们是否在OpenList或CloseList当中。如果不在,则将它们加入 OpenList,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。一个格子的“父节点”代表它的来路,在输出最终路线时会用到。刚才的1-3步,就是局部寻路的步骤。重复2,3步,直到找到终点,或把所有可达的格子用尽为止。

代码

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;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) {List<Grid> openList = new ArrayList<>();List<Grid> closeList = new ArrayList<>();openList.add(start);while (openList.size() > 0) {Grid currentGrid = findMinGrid(openList);//在openList找到F值最小的点openList.remove(currentGrid);//在openList移除当前格子closeList.add(currentGrid);//添加到closeListList<Grid> neighbors = findNeighbors(currentGrid, openList, closeList);for (Grid grid : neighbors) {if (!openList.contains(grid)) {//相邻节点不在openList,标记"父节点",G,H,F并放入openListgrid.initGrid(currentGrid, end);openList.add(grid);}}for (Grid grid : openList) {//终点在openList中,直接返回终点格子if ((grid.x == end.x) && (grid.y == end.y))return grid;}}return null;//openList用尽,找不到终点,说明终点不可达,返回null}/*** 寻找在OpenList集合中F值最小的*/private static Grid findMinGrid(List<Grid> openList) {Grid grid = openList.get(0);for (Grid _grid : openList) {if (_grid.f < grid.f)grid = _grid;}return grid;}/*** 寻找在格子,周围的格子(在边界内,没有走过的)*/private static List<Grid> findNeighbors(Grid grid, List<Grid> openList, List<Grid> closeList) {List<Grid> gridList = new ArrayList<>();int x = grid.x;int y = grid.y;if (isValidGrid(x, y - 1, openList, closeList))gridList.add(new Grid(x, y - 1));if (isValidGrid(x, grid.y + 1, openList, closeList))gridList.add(new Grid(x, y + 1));if (isValidGrid(x - 1, y, openList, closeList))gridList.add(new Grid(x - 1, y));if (isValidGrid(x + 1, y, openList, closeList))gridList.add(new Grid(x + 1, y));return gridList;}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;if (containGrid(openList, x, y))//是否在openListreturn false;return !containGrid(closeList, x, y);//在closeList,返回false 不在时不满足所有情况,返回true/***  return !containGrid(closeList, x, y); <==>*  if(containGrid(closeList, x, y))*      return false;*  return true;*/}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 {//演示代码,不符合Java Bean规范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;}public void initGrid(Grid parent, Grid end) {this.parent = parent;//设置当前节点的父节点,方便回溯路径this.g = Objects.nonNull(parent) ? (parent.g + 1) : 1;//设置G属性值this.h = Math.abs(this.x - end.x) + Math.abs(this.y - end.y);//设置H属性值this.f = this.g + this.h;//设置F属性值}}public static void main(String[] args) {Grid startGrid = new Grid(2, 1);//起点Grid endGrid = new Grid(2, 5);//终点Grid resultGrid = aStarSearch(startGrid, endGrid);//回溯迷宫路径List<Grid> path = new ArrayList<>();while (Objects.nonNull(resultGrid)) {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("*,");elseSystem.out.print(MAZE[i][j] + ",");}System.out.println();}}}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人間になりたい。

さよならはエモーション 僕は行く ずっと涙こらえ こらえ 忘れてたエモーション 僕は行く ずっと深い霧の 霧の向こうへ『……组建过,那就好。』 属于我的 Crychic,就在那个寒假啊。 或许更早些,始于一次英语单元测同时爆炸了的三个人,经过一次精彩地赶在元旦零点钟声前分解…

【THM】Security Principles(安全原则)-学习

了解安全三元组以及常见的安全模型和原则。本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/securityprinciples 本文相关内容:了解安全三元组以及常见的安全模型和原则。介绍 网络安全已成为一个流行词;每家公司都声称其网络产品或网络服务是安全的,但事实上…

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而,原厂固件的功能相对有限,难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能,还能通过第三方固件实现更丰富的功能,如 DNS 解析、KMS 服务器、USB 管理等。本文旨在为小米 R3G 路由器用户提供详细的刷…

windows知道服务器的内网IP地址如何查看服务器的计算机名称

windows知道服务器的内网IP地址如何查看服务器的计算机名称windows知道服务器的内网IP地址如何查看服务器的计算机名称 nbtstat百度百科 https://baike.baidu.com/item/nbtstat/7578115 windows在局域网内查看ip地址对应的计算机名或者根据计算机名查ip https://blog.csdn.net/…

C++ 使用MIDI库演奏《晴天》

那些在MIDI库里徘徊的十六分音符 终究没能拼成告白的主歌我把周杰伦的《晴天》写成C++的类在每个midiEvent里埋藏故事的小黄花调试器的断点比初恋更漫长而青春不过是一串未导出的cmake工程文件在堆栈溢出的夜晚终将明白有些旋律永远停在#pragma once的注释里有些人永远停在未定…

JUC并发—2.Thread源码分析及案例应用

大纲 1.什么是线程以及并发编程 2.微服务注册中心案例 3.以工作线程模式开启微服务的注册和心跳线程 4.微服务注册中心的服务注册功能 5.微服务注册中心的心跳续约功能 6.微服务的存活状态监控线程 7.以daemon模式运行微服务的存活监控线程 8.一般不常用到的ThreadGroup是什么 …

HashMap 的 put 方法源码分析(JDK 1.8)

一、HashMap 的 put 方法源码分析(JDK 1.8) 以下是 HashMap 的 put 方法的源码(JDK 1.8):hash(key) 方法 hash(key) 方法用于计算键的哈希值:如果键为 null,返回 0。否则,返回键的哈希码与高 16 位的异或结果(目的是减少哈希冲突)。putVal 方法 putVal 方法是 HashMa…

第二章笔记

2.1用二进制数表示计算机信息的原因 IC的所有引脚,只有直流电压0V或5V 两个状态。也就是说,IC的一个引脚,只能表示两个状态。 计算机处理信息的最小单位——位,就相当于二进制中的一位。位的英文bit是二进制数位(binary digit)的缩写。 二进制数的位数一般是8位、16位、3…

基金年结、结账、关账和开账

基金年结、结账、关账和开账是基金公司年底财务工作中的重要环节,不仅涉及资产、负债、所有者权益等七大要素的核算,还需要进行全面的账务处理和数据校验。本文将详细解读基金年结的背景、目的、概念以及具体流程,帮助大家深入了解这一复杂而关键的财务操作过程。其实年结不…

分组密码工作模式-CBC

CBC全称密文分组链接工作模式:是分组密码算法的一种工作模式,其特征是将当前的明文分组与前一密文分组进行异或运算后再进行加密得到当前的密文分组。 在CBC模式下,每个明文分组在加密之前,先与反馈至输入端的前一组密文分组按位异或后,再送至加密模块进行加密。其中,IV是…

基于AutoEncode自编码器的端到端无线通信系统matlab误码率仿真

1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印):仿真操作步骤可参考程序配套的操作视频。2.算法涉及理论知识概要自编码器是一种特殊的神经网络结构,主要由编码器(Encoder)和解码器(Decoder)两部分组成。自编码器的目标是最小化重构误差,常用的重构误…