package xu.problem.pathfinding; import core.problem.Action; import core.problem.State; import core.runner.HeuristicType; import core.solver.Node; import core.solver.heuristic.Predictor; import java.util.ArrayList; import java.util.EnumMap; /** * PathFinding问题的状态 * 位置状态,表示寻路机器人在什么位置 */ public class Position extends State { public static final int SCALE = 10; //单元格的边长 public static final double ROOT2 = 1.4; //2的平方根 //可移动的方向:四个方向或者八个方向 private static final int MOVETYPE = 1; //八个方向移动 private static final Direction[][] directions = new Direction[2][]; static{ //四个方向移动 directions[0] = new Direction[]{Direction.N, Direction.E, Direction.S, Direction.W}; //八个方向移动 directions[1] = Direction.values(); } //机器人在场地中的位置 private final Point point; public Position(int row, int col) { this.point = new Point(row, col); } @Override public void draw() { System.out.println(this); } /** * 当前状态采用action而进入的下一个状态 * * @param action 当前状态下,一个可行的action * @return 下一个状态 */ @Override public State next(Action action) { //当前Action所带来的位移量 Direction dir = ((Move)action).getDirection(); int[] offsets = Direction.offset(dir); //生成新状态所在的点 int col = getCol() + offsets[0]; int row = getRow() + offsets[1]; return new Position(row, col); } @Override public Iterable actions() { ArrayList moves = new ArrayList<>(); for (Direction d : directions[MOVETYPE]) moves.add(new Move(d)); return moves; } //枚举映射,存放不同类型的启发函数 private static final EnumMap predictors = new EnumMap<>(HeuristicType.class); static{ predictors.put(HeuristicType.PF_EUCLID, (state, goal) -> ((Position)state).euclid((Position)goal)); predictors.put(HeuristicType.PF_MANHATTAN, (state, goal) -> ((Position)state).manhattan((Position)goal)); predictors.put(HeuristicType.PF_GRID, (state, goal) -> ((Position)state).gridDistance((Position)goal)); } public static Predictor predictor(HeuristicType type){ return predictors.get(type); } //两个点之间的Grid距离,尽量走对角线 private int gridDistance(Position goal) { int width = Math.abs(this.getCol() - goal.getCol()); int height = Math.abs(this.getRow() - goal.getRow()); if (width > height) { return (width - height) * SCALE + height * (int) (SCALE * ROOT2); } else{ return (height - width) * SCALE + width * (int) (SCALE * ROOT2); } } //两个点之间的曼哈顿距离乘以SCALE private int manhattan(Position goal) { return this.point.manhattan(goal.point) * SCALE; } //两个点之间的欧几里德距离 private int euclid(Position goal) { return (int) (this.point.euclid(goal.point) * SCALE); } @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof Position ) { Position another = (Position) obj; //两个Node对象的状态相同,则认为是相同的 return this.point.equals(another.point); } return false; } @Override public int hashCode() { return point.hashCode(); } @Override public String toString() { return point.toString(); } public int getRow() { return point.getX(); } public int getCol() { return point.getY(); } }