A*自动寻路算法—java版(八方向版)

2023-11-16

上一篇博客分享了Java版的自动寻路,但是只是上下左右四个方向的,今天把八方向的也分享出来。


既然四方向的已经成功了,那么改进成八方向的,只要注意两个地方就可以了,一个是获取四周方块的时候,一个是移动的时候。


一、获取四周方块

在autofindway.java中添加静态变量,用来标识上下左右四个方向是否可通过。

//在获取上下左右四个方块的时候,判断各个方块是否满足条件(比如:只有右边和下边的方块都可通过的时候,才能去判断右下方的方块是否满足条件,否则就是穿墙了)
	private static boolean top = false;
	private static boolean down = false;
	private static boolean left = false;
	private static boolean right = false;

在获取四周方块的方法aroundFk中,考虑左上、右上、右下、左下四个方块的判断。

其中,上下左右四个方块的判断中,如果可以通过,则将对应的方向(top/down/left/right)标识为true。只有在左边和上边方块都是true的时候,才能去判断左上方方块是否满足条件,否则就存在穿墙现象。


比如下图的四种情况,红点想要移动到左上方的绿点,只有左边和上边(①)都可穿过的时候才能正常移动过去。像图②③④这三种情况如果直接移动,都存在穿墙的现象。



代码如下:只要替换掉四方向版本中的aroundFk就可以了。

/**
	 * 获取周围方块
	 * ①判断是否超越边界
	 * ②判断是否是障碍物/已计算过的方块
	 * @param fk	中心方块 
	 * @return	周围方块结集合
	 */
	public List<FangKuaiPosition> aroundFk(FangKuaiPosition fk){
		//重置
		top = false;
		down = false;
		left = false;
		right = false;
		List<FangKuaiPosition> list = new ArrayList<FangKuaiPosition>();
		//判断上面的方块是否符合条件
		//判断是否超过越边界
		if(fk.getY() - 1 >= 0){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX(), fk.getY() - 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				top = true;//上方方块符合条件
			}
		}
		
		//判断下面的方块是否符合条件
		if(fk.getY() + 1 < BasePanel.heightLength){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX(), fk.getY() + 1, fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				down = true;//下方方块符合条件
			}
		}
		
		//判断左面的方块是否符合条件
		if(fk.getX() - 1 >= 0){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() - 1, fk.getY(), fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				left = true;//左方方块符合条件
			}
		}
		//判断右面的方块是否符合条件
		if(fk.getX() + 1 < BasePanel.widthLength){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY(), fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				right = true;//右方方块符合条件
			}
		}
		
		//左上方方块校验(左移一格不超过边界&&上移一格不超过边界&&左边方块符合条件&&上边方块符合条件,下面的类似原理)
		if(fk.getX() - 1 >= 0 && fk.getY() - 1 >= 0 && left && top){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() - 1, fk.getY() - 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//右上方方块校验
		if(fk.getX() + 1 < BasePanel.widthLength && fk.getY() - 1 >= 0 && right && top){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() - 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//右下方方块校验
		if(fk.getX() + 1 < BasePanel.widthLength && fk.getY() + 1 < BasePanel.heightLength && right && down){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() + 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//左下方方块校验
		if(fk.getX() - 1 >= 0 && fk.getY() + 1 < BasePanel.heightLength && left && down){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() + 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		//将中心方块添加到已处理过的集合中
		BasePanel.closedList.add(fk);
		getFGH(list,fk);
		return list;
	}

二、移动

在basepanel.java中的movePanel方法里面,四方向的版本只做了上下左右四个方向的移动判断,所以这里需要将左上、右上、右下、左下的移动判断添加进来。同样,也是替换掉四方向版本中的这个movePanel方法就可以了。


/**
	 * 方块移动
	 * @param wayList	移动路线
	 * @throws InterruptedException
	 */
	public void movePanel(List<FangKuaiPosition> wayList) throws InterruptedException{
		
		if(wayList == null || wayList.size() == 0){
			System.out.println("无法 到达终点 !");
			return;
		}
		
		for(int i = wayList.size() - 2; i >= 0; i--){
			FangKuaiPosition fk = wayList.get(i);
			
			//向左上移动
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() > fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右上移动
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() < fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右下移动
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() < fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向左下移动
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() > fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向上
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() == fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX(), cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向下
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() == fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX(), cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向左
			while(cat.getX() > fk.getX() * MyPanel.size && cat.getY() == fk.getY() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY(), MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右
			while(cat.getX() < fk.getX() * MyPanel.size && cat.getY() == fk.getY() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY(), MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
		}
		System.out.println("寻路结束!");
	}


好了,给大家展示一下结果:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

A*自动寻路算法—java版(八方向版) 的相关文章

  • 如何在一行中将字符串数组转换为双精度数组

    我有一个字符串数组 String guaranteedOutput Arrays copyOf values values length String class 所有字符串值都是数字 数据应转换为Double QuestionJava 中
  • 我需要在 Spring 中检查每个控制器中的有效会话吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 假设在 Spring Mvc 的 Web 应用程序中 我们是否需要检查每个控制器或 jsps 中的有效会话 我该如何解决 MVC 中的
  • 在Windows上安装Java 11 OpenJDK(系统路径问题)

    Java 11 最近发布了 众所周知 这个版本没有安装文件 当然 要在没有安装程序的情况下安装 Java 我将系统设置 PATH 和 JAVA HOME 设置为解压缩 Java 11 的文件夹的地址 根据对类似问题的已接受回复建议 唯一的事
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • manifest.mf 文件的附加内容的约定?

    Java JAR 中的 MANIFEST MF 文件是否有任何超出 MANIFEST MF 约定的约定 JAR规范 http download oracle com javase 1 4 2 docs guide jar jar html
  • 如何查找 Android 设备中的所有文件并将它们放入列表中?

    我正在寻求帮助来列出 Android 外部存储设备中的所有文件 我想查找所有文件夹 包括主文件夹的子文件夹 有办法吗 我已经做了一个基本的工作 但我仍然没有得到想要的结果 这不起作用 这是我的代码 File files array file
  • Java8无符号算术

    据广泛报道 Java 8 具有对无符号整数的库支持 然而 似乎没有文章解释如何使用它以及有多少可能 有些函数 例如 Integer CompareUnsigned 很容易找到 并且似乎可以实现人们所期望的功能 但是 我什至无法编写一个简单的
  • 如何为 Gson 编写自定义 JSON 反序列化器?

    我有一个 Java 类 用户 public class User int id String name Timestamp updateDate 我收到一个包含来自 Web 服务的用户对象的 JSON 列表 id 1 name Jonas
  • 当分配给变量时,我可以以某种方式重用 Gremlin GraphTraversals 代码吗?

    我有看起来像这样的 GraphTraversals attrGroup GraphTraversal
  • hibernate总是自己删除表中的所有数据

    您好 我正在开发一个 spring mvc 应用程序 它使用 hibernate 连接到存储文件的 mysql 数据库 我有两个方法 一个方法添加我选择的特定文件路径中的所有文件 另一种方法调用查询以返回从 mysql 存储的文件列表 问题
  • 序列化对象以进行单元测试

    假设在单元测试中我需要一个对象 其中所有 50 个字段都设置了一些值 我不想手动设置所有这些字段 因为这需要时间而且很烦人 不知何故 我需要获得一个实例 其中所有字段都由一些非空值初始化 我有一个想法 如果我要调试一些代码 在某个时候我会得
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • Java直接内存:在自定义类中使用sun.misc.Cleaner

    在 Java 中 NIO 直接缓冲区分配的内存通过以下方式释放 sun misc Cleaner实例 一些比对象终结更有效的特殊幻像引用 这种清洁器机制是否仅针对直接缓冲区子类硬编码在 JVM 中 或者是否也可以在自定义组件中使用清洁器 例
  • 将多模块 Maven 项目导入 Eclipse 时出现问题 (STS 2.5.2)

    我刚刚花了最后一个小时查看 Stackoverflow com 上的线程 尝试将 Maven 项目导入到 Spring ToolSuite 2 5 2 中 Maven 项目有多个模块 当我使用 STS 中的 Import 向导导入项目时 所
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • Keycloak - 自定义 SPI 未出现在列表中

    我为我的 keycloak 服务器制作了一个自定义 SPI 现在我必须在管理控制台上配置它 我将 SPI 添加为模块 并手动安装 因此我将其放在 module package name main 中 并包含 module xml 我还将其放
  • Java - 不要用 bufferedwriter 覆盖

    我有一个程序可以将人员添加到数组列表中 我想做的是将这些人也添加到文本文件中 但程序会覆盖第一行 因此这些人会被删除 如何告诉编译器在下一个空闲行写入 import java io import java util import javax
  • 如何配置eclipse以保持这种代码格式?

    以下代码来自 playframework 2 0 的示例 Display the dashboard public static Result index return ok dashboard render Project findInv
  • 如何测试 spring-security-oauth2 资源服务器安全性?

    随着 Spring Security 4 的发布改进了对测试的支持 http docs spring io spring security site docs 4 0 x reference htmlsingle test我想更新我当前的
  • KeyPressed 和 KeyTyped 混淆[重复]

    这个问题在这里已经有答案了 我搜索过之间的区别KeyPressedand KeyTyped事件 但我仍然不清楚 我发现的一件事是 Keypressed 比 KeyTyped 首先被触发 请澄清一下这些事件何时被准确触发 哪个适合用于哪个目的

随机推荐

  • ue中的经纬高转xyz的问题

    在ue中 做了个地球仪 发现经纬度转地心坐标系老是出问题 后来发现 是转ue时 x y坐标要互换 也对 因为在cesium for unreal中还有一系列ecef转ue的相关函数 即下面的代码中 xy需要互换 在ue中才能正常使用 偏心率
  • 【图解网络协议】面试官:三次握手都不会,回去等通知吧

    文章目录 一 网络基础知识准备 1 OSI七层网络模型总结 2 TCP IP协议总结 3 TCP协议流程 4 UDP协议 5 什么是socket 二 http协议 1 什么是http协议 2 http 1 0 与 http 1 1的区别 3
  • 香农公式简介

    信道容量 指信道中信息无差错传输的最大速率 信道模型中定义了两种广义信道 调制信道和编码信道 调制信道是一种连续信道 可以用连续信道的信道容量来表征 编码信道是一种离散信道 可以用离散信道的信道容量来表征 香农公式 设信道带宽为B 单位为H
  • 五种IO模型(详解+形象例子说明)

    在网络环境下 通俗的讲 将IO分为两步 1 等 2 数据搬迁 如果要想提高IO效率 需要将等的时间降低 五种IO模型包括 阻塞IO 非阻塞IO 信号驱动IO IO多路转接 异步IO 其中 前四个被称为同步IO 在介绍五种IO模型时 我会举生
  • 给一个正整数n,求出位数。并按正序输出,逆序输出

    求出位数 思路 通过让给定的正整数n整除10 且每整除一次让统计位数的变量count自增一 返回count得到位数 include
  • 华硕主板固态硬盘不识别_[主板] 开机后无法识别硬盘或SSD的故障排除方式

    1 尝试更新官网最新的BIOS版本 可参考FAQ 华硕EZ Flash 3 介绍 2 在计算机开机后 立刻按压键盘上的 delete 键 在BIOS EZ Mode 页面的 Storage Information 字段 确认是否可以显示所接
  • 使用EasyExcel生成表格并且返回File对象

    通过此方法 可以导出表格并且存入File对象中进行其他的操作 这里通过File来进行异步存储到文件服务器 用于下载中心 public static
  • myeclipse10配置tomcat详细过程

    首先确保你已经成功的安装 了myeclipse10和tomcat 我用的是tomcat6 1 在myeclipse10中添加tomcat 选择属性preferences之后进入配置框 选择servers下的tomcat6 视你自己的版本而定
  • 【翻译】软件表现不佳,未来取决于这种情况的改变

    如果一件事不能永远进行下去 它就不会 赫伯 斯坦法则 科技行业的未来会是什么样子 从现在到2030年 我们所有人面临的挑战不再是我们将如何说服世界 或更直接地说 我们的老板或客户 成为碳零 无论我们是否愿意 这都会到来 我们的新问题是 作为
  • 如何阅读他人的项目源代码程序

    阅读他人的项目源代码步骤 备份并编译运行代码 熟悉项目编程语言的语法和惯例用语 看项目文档 有机会可向项目开发人员请教 自上而下构建项目程序的系统架构 建立系统架构和功能逻辑之间的关联 核心代码重点剖析与注释 调整心态 反复阅读 工欲善其事
  • Vue3只读代理---readonly、isReadonly、shallowReadonly

    readonly 获取一个对象 响应式或纯对象 或 ref 并返回原始代理的只读代理 不能给属性重新赋值 只读代理是递归的 访问的任何嵌套 property 也是只读的
  • springmvc源码学习(二十四)异步请求管理器WebAsyncManager初始化

    目录 前言 一 WebAsyncManager初始化 二 参数的初始化 三 自定义参数 总结 前言 Springmvc的异步执行请求是有异步管理器WebAsyncManager来控制的 一 WebAsyncManager初始化 1 在请求到
  • 大数据--Hadoop环境部署(4)Hadoop集群部署

    Hadoop集群的部署方式分为三种 分别是独立模式 Standalone mode 伪分布式模式 Pseudo Distributed mode 和完全分布式模式 Cluster mode 独立模式和伪分布式模式主要用于学习和调试 完全分布
  • 数据圈最全的数据分析&产品文章合集

    关注公众号 回复 进群 与3万 数据人交流 公众号介绍 一个数据人的自留地 成立于2020年2月25日 目前发表原创300 篇 拥有3万 粉丝 交流群10 个 连载数据产品 数据分析 画像标签 策略算法 运营增长 求职面试等20多个方向的文
  • Spring Boot Kafka - 序列化和反序列化JSON

    文章目录 Spring Boot Kafka 序列化和反序列化JSON 前言 配置JsonSerializer和JsonDeserializer 定义一个Model类 Producer类 Consumer类 Controller类 测试 小
  • EMNLP 2020 Beyond Instructional Videos: Probing for More Diverse Visual-Textual Grounding on YouTube

    动机 从无标签的网络视频中进行预训练已经迅速成为在许多视频待处理任务中实际获得高性能的的手段 通过预测语音内容和自动语音识别 ASR token之间的grounded关系来学习特征 然而 先前的训练前工作仅限于教学录像 作者希望这个领域是相
  • 1.uniapp全局状态管理

    概念 把多个组件之间共享数据抽离出来 通过一个 单例模式 进行管理 工具 具备全局状态管理的库 Vuex 全局状态管理中的库 步骤 1 建立Store文件夹 2 建立index js文件 3 在main js中注册Vue插件 4 测试Vue
  • POI实现word转HTML!呵呵!!!

    那些说POI把word转HTML如何如何完美的人们 copy东copy西 有想过转出来的格式与word不一致么 唉
  • 动态规划法--求数组中最大子集合的和

    例题 给定一个数组int a 9 1 3 5 1 7 5 3 1 计算数组中连续的最大和以及出现的位置 输出 下标1到5位连续的最大和为15 首先看到这种题目 我的第一反应 就是用冒泡排序的思想去做 public class zuoye p
  • A*自动寻路算法—java版(八方向版)

    上一篇博客分享了Java版的自动寻路 但是只是上下左右四个方向的 今天把八方向的也分享出来 既然四方向的已经成功了 那么改进成八方向的 只要注意两个地方就可以了 一个是获取四周方块的时候 一个是移动的时候 一 获取四周方块 在autofin