package com.zy.acs.manager.core.service.astart.domain; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; /** * A*寻路算法Node节点 */ @Slf4j @Data public class AStarNavigateNode implements Comparable, Cloneable, Serializable { private static final long serialVersionUID = 1L; private int x; //坐标x private int y; //坐标y private int turnCount; //转弯次数 private int G; //已经花费的步数 private int H; //将要花费的步数 private int F; //综合花费的步数 private AStarNavigateNode parent; //父节点 private Integer lastDistance; // 距离上个节点距离 private Integer weight; // G 权重 // private boolean turningPoint; //是否为拐点 // private Integer moveDistance; // 总行走距离 // private String direction; //行走方向 private String codeData; public AStarNavigateNode(int x, int y) { this.x = x; this.y = y; this.turnCount = 0; } public AStarNavigateNode(int x, int y, String codeData) { this.x = x; this.y = y; this.turnCount = 0; this.codeData = codeData; } //通过结点的坐标和目标结点的坐标可以计算出F, G, H三个属性 //需要传入这个节点的上一个节点和最终的结点 public void initNode(AStarNavigateNode father, AStarNavigateNode end) { this.parent = father; if (this.parent != null) { //走过的步数等于父节点走过的步数加一 this.G = this.parent.G + Optional.ofNullable(this.lastDistance).orElse(0) + Optional.ofNullable(this.weight).orElse(0); } else { //父节点为空代表它是第一个结点 this.G = 0; } //以下计算方案为算法原始方案,没有去拐点方案。已被Solution计算时自动覆盖。 //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加) this.H = Math.abs(this.x - end.x) + Math.abs(this.y - end.y); this.F = this.G + this.H; } @Override public int compareTo(AStarNavigateNode o) { return Integer.compare(this.F, o.F); } @Override public AStarNavigateNode clone() { try { return (AStarNavigateNode) super.clone(); } catch (CloneNotSupportedException e) { log.error(this.getClass().getSimpleName(), e); } return null; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof AStarNavigateNode)) return false; AStarNavigateNode that = (AStarNavigateNode) obj; return this.x == that.x && this.y == that.y // && this.turnCount == that.turnCount // ** 转弯优化,严重影响性能 ; } @Override public int hashCode() { return Objects.hash( this.x , this.y // , this.turnCount // ** 转弯优化,严重影响性能 ); } private void print() { AStarNavigateNode finishNode = this.clone(); ArrayList navigateNodes = new ArrayList<>(); while (finishNode != null) { navigateNodes.add(finishNode); System.out.println("node:" + finishNode.getCodeData() + ", g:" + finishNode.getG() + ", h:" + finishNode.getH() + ", f:" + finishNode.getF()); finishNode = finishNode.getParent(); } Collections.reverse(navigateNodes); List navigatePath = navigateNodes.stream().map(AStarNavigateNode::getCodeData).collect(Collectors.toList()); System.out.println(navigatePath.toString()); } }