Java 实现*以解决难题

Java 实现*以解决难题,java,artificial-intelligence,a-star,Java,Artificial Intelligence,A Star,我正在尝试实现一个a*算法来解决一个滑动难题,但我无法让这个算法工作,我已经为此工作了几天,但老实说,我不知道现在发生了什么。我一直在关注维基百科和“RedBlobGame”博客上的伪代码,但现在我完全迷路了 这是dea*算法 ArrayList<Node> open = new ArrayList<Node>(); ArrayList<Node> closed = new ArrayList<Node>(); Node

我正在尝试实现一个a*算法来解决一个滑动难题,但我无法让这个算法工作,我已经为此工作了几天,但老实说,我不知道现在发生了什么。我一直在关注维基百科和“RedBlobGame”博客上的伪代码,但现在我完全迷路了

这是dea*算法

    ArrayList<Node> open = new ArrayList<Node>();
    ArrayList<Node> closed = new ArrayList<Node>();

    Node goal = new Node(myBoard.getGoalBoard());

    Node start = new Node(mb);
    start.setH(this.heuristic.calculate(start, goal));
    start.setG(0);
    start.setDepth(0);

    open.add(start);

    Node current = null;
    while(!open.isEmpty() && !myBoard.stopAlgorithm){
        current = getLowest(open);
        if(current.isGoal()){
            System.out.println("done");
            return finalise(current.getBoard(), displaySearch, current.getDepth());
        }
        open.remove(current);
        closed.add(current);
        int depth = current.getDepth() + 1;
        ArrayList<Node> succesors = current.getSuccessors(depth);
        for(Node node: succesors){
            node.setH(this.heuristic.calculate(node, goal));
            node.setG(current.getG() + 1);
            node.setParent(current);
            if(!closed.contains(node)){
                if(!open.contains(node)){
                    open.add(node);
                }else{
                    Node openN = open.get(open.indexOf(node));
                    if(node.getG() < openN.getG()){
                        openN.setG(node.getG());
                        openN.setParent(node.getParent());
                    }
                }
            }
        }
    }
    System.out.println("path not finded");
    return null;
ArrayList open=new ArrayList();
ArrayList closed=新建ArrayList();
节点目标=新节点(myBoard.getGoalBoard());
节点开始=新节点(mb);
setH(this.heuristic.calculate(start,goal));
start.setG(0);
start.setDepth(0);
打开。添加(开始);
节点电流=零;
而(!open.isEmpty()&&!myBoard.stopAlgorithm){
电流=最低(打开);
if(current.isGoal()){
系统输出打印项次(“完成”);
返回finalize(current.getBoard(),displaySearch,current.getDepth());
}
打开。移除(当前);
已关闭。添加(当前);
int depth=current.getDepth()+1;
ArrayList Successors=当前.getSuccessions(深度);
用于(节点:成功者){
setH(this.heuristic.calculate(node,goal));
node.setG(current.getG()+1);
node.setParent(当前);
如果(!closed.contains(节点)){
如果(!open.contains(节点)){
打开.添加(节点);
}否则{
Node openN=open.get(open.indexOf(Node));
if(node.getG()
有时他们会找到解决方案,有时,只是不断寻找和扩展更多可能的状态,我看不出问题在哪里。有什么帮助吗

这是节点类中的代码
而启发式演算(本例中为曼哈顿)

这只是一个猜测。我已经有一段时间没有编写*了,我看不出您是如何实现node类的。我认为不应该使用node.setG(current.getG()+1)设置G,或者如果node已经添加到打开列表中,则不应该将父节点设置为current

尝试:

int-depth=current.getDepth()+1;
ArrayList Successors=当前.getSuccessions(深度);
用于(节点:成功者){
如果(!closed.contains(节点)&&!open.contains(节点)){
setH(this.heuristic.calculate(node,goal));
node.setG(current.getG()+1);
node.setParent(当前);
打开.添加(节点);
} 
}
这是一个更完整的版本,似乎适合我(仅使用3 x 3进行测试。大多数代码只是设置状态。需要注意的是:为了提高效率,您不需要搜索列表以查看其中是否包含状态。最好使用哈希集,但这需要实现hashCode()和equals()一致性。您的IDE可能会生成它们

public static class BoardState {

    int positions[];

    private int priority;

    /**
     * Get the value of priority
     *
     * @return the value of priority
     */
    public int getPriority() {
        return priority;
    }

    /**
     * Set the value of priority
     *
     * @param priority new value of priority
     */
    public void setPriority(int priority) {
        this.priority = priority;
    }

    private int distFromGoal;

    /**
     * Get the value of distFromGoal
     *
     * @return the value of distFromGoal
     */
    public int getDistFromGoal() {
        return distFromGoal;
    }

    /**
     * Set the value of distFromGoal
     *
     * @param distFromGoal new value of distFromGoal
     */
    public void setDistFromGoal(int distFromGoal) {
        this.distFromGoal = distFromGoal;
    }

    private BoardState goal;

    /**
     * Get the value of goal
     *
     * @return the value of goal
     */
    public BoardState getGoal() {
        return goal;
    }

    /**
     * Set the value of goal
     *
     * @param goal new value of goal
     */
    public void setGoal(BoardState goal) {
        this.goal = goal;
    }

    private int depth;

    /**
     * Get the value of depth
     *
     * @return the value of depth
     */
    public int getDepth() {
        return depth;
    }

    /**
     * Set the value of depth
     *
     * @param depth new value of depth
     */
    public void setDepth(int depth) {
        this.depth = depth;
    }

    private BoardState prev;

    /**
     * Get the value of prev
     *
     * @return the value of prev
     */
    public BoardState getPrev() {
        return prev;
    }

    /**
     * Set the value of prev
     *
     * @param prev new value of prev
     */
    public void setPrev(BoardState prev) {
        this.prev = prev;
    }

    public BoardState(BoardState other) {
        this.positions = new int[9];
        System.arraycopy(other.positions, 0, this.positions, 0, positions.length);
        this.depth = other.depth + 1;
        this.goal = other.goal;
        this.prev = other;
    }

    private BoardState() {

    }

    public static BoardState goal() {
        List<Integer> l = new ArrayList<Integer>();
        IntStream.range(0, 9).forEach(i -> l.add(i));
        BoardState r = new BoardState();
        r.positions = new int[9];
        Arrays.setAll(r.positions, i -> l.get(i).intValue());
        return r;
    }

    public static BoardState random() {
        List<Integer> l = new ArrayList<Integer>();
        IntStream.range(0, 9).forEach(i -> l.add(i));
        Collections.shuffle(l);
        BoardState r = new BoardState();
        r.positions = new int[9];
        Arrays.setAll(r.positions, i -> l.get(i).intValue());
        return r;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + Arrays.hashCode(this.positions);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final BoardState other = (BoardState) obj;
        if (!Arrays.equals(this.positions, other.positions)) {
            return false;
        }
        return true;
    }

    int valueAt(int r, int c) {
        int pos = r * 3 + c;
        for (int i = 0; i < positions.length; i++) {
            if (pos == positions[i]) {
                return i;
            }
        }
        throw new RuntimeException("invalid board or position");
    }

    void print() {
        System.out.println("depth = " + depth);
        for (int r = 0; r < 3; r++) {
            for (int c = 0; c < 3; c++) {
                System.out.print(this.valueAt(r, c) + "\t");
            }
            System.out.println("");
        }

    }

    int distance(BoardState other) {
        int dist = 0;
        for (int i = 0; i < positions.length; i++) {
            int c0 = this.positions[i] % 3;
            int r0 = this.positions[i] / 3;
            int c1 = other.positions[i] % 3;
            int r1 = other.positions[i] / 3;
            dist += Math.abs(r0 - r1) + Math.abs(c0 - c1);
        }
        return dist;
    }

    public List<BoardState> moves() {
        List<BoardState> newList = new ArrayList<>();
        int r0 = this.positions[0] / 3;
        int c0 = this.positions[0] % 3;
        if (r0 > 0) {
            BoardState up = new BoardState(this);
            up.positions[0] = (r0 - 1) * 3 + c0;
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == up.positions[0]) {
                    up.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(up);
        }
        if (r0 < 2) {
            BoardState down = new BoardState(this);
            down.positions[0] = (r0 + 1) * 3 + c0;
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == down.positions[0]) {
                    down.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(down);
        }
        if (c0 > 0) {
            BoardState left = new BoardState(this);
            left.positions[0] = r0 * 3 + (c0 - 1);
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == left.positions[0]) {
                    left.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(left);
        }
        if (c0 < 2) {
            BoardState right = new BoardState(this);
            right.positions[0] = r0 * 3 + (c0 + 1);
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == right.positions[0]) {
                    right.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(right);
        }
        for (BoardState move : newList) {
            move.setDistFromGoal(move.distance(goal));
            move.setPriority(move.distFromGoal + move.depth);
        }
        return newList;
    }
}
公共静态类BoardState{
int位置[];
私人优先权;
/**
*获取优先级的值
*
*@返回优先级的值
*/
public int getPriority(){
返回优先级;
}
/**
*设置优先级的值
*
*@param priority优先级的新值
*/
公共无效设置优先级(整数优先级){
优先权=优先权;
}
私人目标;
/**
*获取distFromGoal的值
*
*@返回distFromGoal的值
*/
public int getDistFromGoal(){
回归目标;
}
/**
*设置distFromGoal的值
*
*@param distFromGoal distFromGoal的新值
*/
public void setDistFromGoal(int distFromGoal){
this.distFromGoal=distFromGoal;
}
私营部门和国家目标;
/**
*获得目标的价值
*
*@返回目标值
*/
公共董事会状态getGoal(){
回归目标;
}
/**
*设定目标的价值
*
*@param-goal目标的新值
*/
公共无效设置目标(董事会状态目标){
这个。目标=目标;
}
私有整数深度;
/**
*获取深度的值
*
*@返回深度值
*/
公共int getDepth(){
返回深度;
}
/**
*设置深度的值
*
*@param depth深度的新值
*/
公共void setDepth(int-depth){
这个。深度=深度;
}
私人董事会和州议会;
/**
*获取prev的值
*
*@返回prev的值
*/
公共董事会状态getPrev(){
返回上一个;
}
/**
*设置prev的值
*
*@param prev prev的新值
*/
公共无效setPrev(BoardState prev){
this.prev=prev;
}
公共BoardState(BoardState其他){
this.positions=新整数[9];
System.arraycopy(其他.positions,0,this.positions,0,positions.length);
this.depth=other.depth+1;
this.goal=other.goal;
this.prev=其他;
}
私人董事会国家(){
}
公共静态董事会状态目标(){
列表l=新的ArrayList();
IntStream.range(0,9).forEach(i->l.add(i));
BoardState r=新的BoardState();
r、 位置=新整数[9];
setAll(r.positions,i->l.get(i.intValue());
返回r;
}
公共静态BoardState random(){
列表l=新的ArrayList();
IntStream.range(0,9).forEach(i->l.add(i));
收藏。洗牌(l);
BoardState r=新的BoardState();
r、 位置=新整数[9];
setAll(r.positions,i->l.get(i.intValue());
返回r;
}
@凌驾
公共int hashCode(){
int hash=7;
hash=83*hash+Arrays.hashCode(this.positions);
返回散列;
}
@凌驾
公共布尔
public static class BoardState {

    int positions[];

    private int priority;

    /**
     * Get the value of priority
     *
     * @return the value of priority
     */
    public int getPriority() {
        return priority;
    }

    /**
     * Set the value of priority
     *
     * @param priority new value of priority
     */
    public void setPriority(int priority) {
        this.priority = priority;
    }

    private int distFromGoal;

    /**
     * Get the value of distFromGoal
     *
     * @return the value of distFromGoal
     */
    public int getDistFromGoal() {
        return distFromGoal;
    }

    /**
     * Set the value of distFromGoal
     *
     * @param distFromGoal new value of distFromGoal
     */
    public void setDistFromGoal(int distFromGoal) {
        this.distFromGoal = distFromGoal;
    }

    private BoardState goal;

    /**
     * Get the value of goal
     *
     * @return the value of goal
     */
    public BoardState getGoal() {
        return goal;
    }

    /**
     * Set the value of goal
     *
     * @param goal new value of goal
     */
    public void setGoal(BoardState goal) {
        this.goal = goal;
    }

    private int depth;

    /**
     * Get the value of depth
     *
     * @return the value of depth
     */
    public int getDepth() {
        return depth;
    }

    /**
     * Set the value of depth
     *
     * @param depth new value of depth
     */
    public void setDepth(int depth) {
        this.depth = depth;
    }

    private BoardState prev;

    /**
     * Get the value of prev
     *
     * @return the value of prev
     */
    public BoardState getPrev() {
        return prev;
    }

    /**
     * Set the value of prev
     *
     * @param prev new value of prev
     */
    public void setPrev(BoardState prev) {
        this.prev = prev;
    }

    public BoardState(BoardState other) {
        this.positions = new int[9];
        System.arraycopy(other.positions, 0, this.positions, 0, positions.length);
        this.depth = other.depth + 1;
        this.goal = other.goal;
        this.prev = other;
    }

    private BoardState() {

    }

    public static BoardState goal() {
        List<Integer> l = new ArrayList<Integer>();
        IntStream.range(0, 9).forEach(i -> l.add(i));
        BoardState r = new BoardState();
        r.positions = new int[9];
        Arrays.setAll(r.positions, i -> l.get(i).intValue());
        return r;
    }

    public static BoardState random() {
        List<Integer> l = new ArrayList<Integer>();
        IntStream.range(0, 9).forEach(i -> l.add(i));
        Collections.shuffle(l);
        BoardState r = new BoardState();
        r.positions = new int[9];
        Arrays.setAll(r.positions, i -> l.get(i).intValue());
        return r;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + Arrays.hashCode(this.positions);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final BoardState other = (BoardState) obj;
        if (!Arrays.equals(this.positions, other.positions)) {
            return false;
        }
        return true;
    }

    int valueAt(int r, int c) {
        int pos = r * 3 + c;
        for (int i = 0; i < positions.length; i++) {
            if (pos == positions[i]) {
                return i;
            }
        }
        throw new RuntimeException("invalid board or position");
    }

    void print() {
        System.out.println("depth = " + depth);
        for (int r = 0; r < 3; r++) {
            for (int c = 0; c < 3; c++) {
                System.out.print(this.valueAt(r, c) + "\t");
            }
            System.out.println("");
        }

    }

    int distance(BoardState other) {
        int dist = 0;
        for (int i = 0; i < positions.length; i++) {
            int c0 = this.positions[i] % 3;
            int r0 = this.positions[i] / 3;
            int c1 = other.positions[i] % 3;
            int r1 = other.positions[i] / 3;
            dist += Math.abs(r0 - r1) + Math.abs(c0 - c1);
        }
        return dist;
    }

    public List<BoardState> moves() {
        List<BoardState> newList = new ArrayList<>();
        int r0 = this.positions[0] / 3;
        int c0 = this.positions[0] % 3;
        if (r0 > 0) {
            BoardState up = new BoardState(this);
            up.positions[0] = (r0 - 1) * 3 + c0;
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == up.positions[0]) {
                    up.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(up);
        }
        if (r0 < 2) {
            BoardState down = new BoardState(this);
            down.positions[0] = (r0 + 1) * 3 + c0;
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == down.positions[0]) {
                    down.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(down);
        }
        if (c0 > 0) {
            BoardState left = new BoardState(this);
            left.positions[0] = r0 * 3 + (c0 - 1);
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == left.positions[0]) {
                    left.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(left);
        }
        if (c0 < 2) {
            BoardState right = new BoardState(this);
            right.positions[0] = r0 * 3 + (c0 + 1);
            for (int i = 1; i < 9; i++) {
                if (this.positions[i] == right.positions[0]) {
                    right.positions[i] = this.positions[0];
                    break;
                }
            }
            newList.add(right);
        }
        for (BoardState move : newList) {
            move.setDistFromGoal(move.distance(goal));
            move.setPriority(move.distFromGoal + move.depth);
        }
        return newList;
    }
}
BoardState goal = BoardState.goal();
System.out.println("goal");
goal.print();
BoardState start = BoardState.random();
System.out.println("start");
start.print();
start.setGoal(goal);
start.setDistFromGoal(start.distance(goal));
start.setPriority(start.distFromGoal + start.depth);
PriorityQueue<BoardState> open = new PriorityQueue<>(Comparator.comparing(b -> b.getPriority()));
open.offer(start);
Set<BoardState> set = new HashSet<>();
set.add(start);
int round = 0;
while (!open.isEmpty()) {
    BoardState cur = open.poll();
    round++;
    if (cur.equals(goal)) {
        System.out.println("goal found after " + round + " rounds");
        System.out.println("printing boards in reverse order");
        do {
            cur.print();
        } while (null != (cur = cur.getPrev()));
        break;
    }
    for (BoardState move : cur.moves()) {
        if (!set.contains(move)) {
            set.add(move);
            open.offer(move);
        }
    }
}