You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
3.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<? extends Action> actions() {
ArrayList<Move> moves = new ArrayList<>();
for (Direction d : directions[MOVETYPE])
moves.add(new Move(d));
return moves;
}
//枚举映射,存放不同类型的启发函数
private static final EnumMap<HeuristicType, Predictor> 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();
}
}