注意:本文适合 有JavaSE基础 勇于尝试 有耐性的读者食用
(正所谓算法开发 学到头了 也就到头了orz)
本文中二维A*思想部分来自于 A* Pathfinding for Beginners - Artificial Intelligence - Tutorials - GameDev.net
在开始之前:
本文不会完全将最终代码贴出,仅取部分作为参考。您的代码理应源于您自己,我们不是为了开发而开发!
撰写本文的想法起始于本人最近进行的一款寻路插件的开发,在研究现有寻路算法时发现了最具优越性的A*寻路算法,但是网络上几乎无法找到三维空间下的A*,即便有也未有详细思路或查询代价过高(此点会在下文说明),故本人特意以MC特性为基础在二维A*的基础上进行改进,经过几天的调试与分析,最终得出本文中完全具备经典二维A*思想的三维A*算法。如若对本文内容持有异议或拥有更好的观点,欢迎各位进行留言!
初始化
我们先了解几个概念:
首先我们将要搜索的地图视作二维的 区分出来两类方块 地面 和 墙面
地面可以是草方块、原石等 可供玩家正常行走的方块
墙面可以是水、岩浆等可视为 无法行走,不进行查找的方块
那么在地面上我们就可以确定搜索的 起点 和 终点
在正式搜索之前 我们先定义一个内部类Node作为节点储存寻路过程中产生的每个结点的位置信息(Location)、父节点(Node)、G值(父节点移动到当前节点的成本)、H值(从当前节点移动到终点的估算成本)以及当前节点与终点的高度差(int)
- public static class Node {
- private final Location location;
- private int height = 0;
- private Node parent = null;
- private int G;
- private int H;
- public Node(Location location) {
- this.location = location;
- }
要注意的是虽然我们在寻路的过程中以Node的实例进行操作,但事实上对位置进行操作时我们仍是对Location进行操作。故为了方便储存与对节点进行操作,我们再定义一个名为NodeSet的类继承HashSet来储存节点与覆写contains、get与remove方法。并实例化一个openList与closeList便于节点的回溯与处理(见下文)
- private final NodeSet openList = new NodeSet(initialCapacity);
- private final NodeSet closeList = new NodeSet(initialCapacity);
- private static class NodeSet extends HashSet<Node> {
- public NodeSet(int initCap) {
- super(initCap);
- }
- public Node get(Location loc) {
- Iterator<Node> iterator = super.iterator();
- while (iterator.hasNext()) {
- Node node = iterator.next();
- if (node.location.equals(loc)) {
- return node;
- }
- }
- return null;
- }
- public boolean contains(Node node) {