0

我正在创建一个深度优先搜索算法,它最终能够解决一个简单的 8 难题。我能够读取文件和目标状态并相应地设置这些变量。

我收到的主要问题是,当我评估当前节点的子节点时,我在 8 个拼图中得到了 2 个“空”值,并且我还得到了一个索引越界异常。

为了获得给定父节点的子节点,我首先必须进行有效移动,然后更新子节点的状态以反映有效移动的结果。

为了执行移动,我检查它是否可行(如果我向左移动它仍然在拼图的范围内),请参阅发布的代码。

在正确打印预期结果时,它在前 2 次移动(向左和向下)中正常运行。

下面是我当前代码执行的输出,你可以看到它正确地左右移动,然后它开始遇到错误。

 Start state:
 120
 345
 678

 after moving left
 102
 345
 678

 Parent: [[C@1b845568
 after moving down
 125
 340
 678

 Parent: [[C@d032cf5
 after moving left
 102
 340
 678

 Parent: [[C@d032cf5
 after moving down
 125
 348
 670

 Parent:
 125
 340
 678

 after moving up
 125
 348
 670

 Parent: [[C@4b7c8f7f
 after moving left
 125
 304
 670

 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
 at dcs.aber.ac.uk.puzzle.PuzzleBoard.swapValues(PuzzleBoard.java:193)
 at dcs.aber.ac.uk.puzzle.PuzzleBoard.moveUp(PuzzleBoard.java:142)
 at dcs.aber.ac.uk.puzzle.DFSSolver.addChildren(DFSSolver.java:155)
 at dcs.aber.ac.uk.puzzle.DFSSolver.search(DFSSolver.java:85)
 at dcs.aber.ac.uk.puzzle.DFSSolver.<init>(DFSSolver.java:27)
     at dcs.aber.ac.uk.puzzle.Driver.main(Driver.java:86)

如您所见,在前两个之后,其余的打印状态都不正确。我将发布我的代码来展示我如何处理板的交换和更新,看看您是否可以确定出现并发症的位置。

    public class Node  {



private Node parent;
private char[][] state = new char[3][3];
private double cost; 
private double heurCost; 
private double funcCost; 
private int depth;

public Node() {
    parent = null;
    }

public Node(Node parent) {
    this.parent = parent;

     for(int i = 0; i < 3; i++){
        for(int j = 0; j< 3; j++){
            state[i][j] = parent.getState()[i][j];

        }   

    } 
} 


public void setParent(Node parent) {

    this.parent = parent;


 }


public char[][] getState() {

    return state;
}

public char[][] copyState(){
    char[][] a = new char[3][3];

    for(int i = 0; i < 3; i++){
         for(int j = 0; j< 3; j++){
             a[i][j] = state[i][j];

        }    

    } 

 return a;
}

 } 

 public class PuzzleBoard {

private  char[][] goalState;
private char[][] currentBoard;
private int emptyRow, emptyCol;
private int outOfPlace;

public PuzzleBoard(char[][] currentState, char[][] goal ){


    this.setCurrentState(currentState);
    this.setGoalState(goal);
    trackEmptySqaure();

}

public void setGoalState(char[][] goalState){

    this.goalState = goalState;

}


public void setCurrentState(char[][] currentState){

    this.currentBoard = currentState;

}



public char[][] getCurrentBoard() {

    return currentBoard;

}

public boolean checkIsGoal(char[][] board){

    for(int i = 0; i < 9; i ++){
        for(int j = 0; j < 3; j ++){
            if(!(goalState[i][j] != (board[i][j]))){

                return false;
            }
        }
    }
    return true;
}

public void trackEmptySqaure() {

    for(int i = 0; i < 3; i ++){
        for (int j = 0; j < 3; j ++){
            if(currentBoard[i][j] == '0'){
                emptyCol = j;
                emptyRow = i;
            }

        }
    }

}

public int getemptyRow() {
    return emptyRow;

}

public int getemptyCol() {
    return emptyCol;

}



public Node moveLeft(Node parent){
    currentBoard = parent.copyState();

    Node result = new Node(parent);

    /* check you can move 'empty' left one space*/
    if(getemptyCol()  > 0){


        swapValues(result.getState(),emptyRow, emptyCol, 1);


        return result;
    }

    return null;
}
public Node moveDown(Node parent){
    currentBoard = parent.copyState();

    Node result = new Node(parent);

    /* check you can move 'empty' down one space*/
    if(getemptyRow()  < 2){


        swapValues(result.getState(),emptyRow, emptyCol,2);

        return result;
    }

    return null;
}

public Node moveUp(Node parent){
    currentBoard = parent.getState();
    Node result = new Node(parent);


    /* check you can move 'empty' up one space*/
    if(getemptyRow() > 0){


        swapValues(result.getState(),emptyRow, emptyCol,2);



        return result;
    }

    return null;
}

public Node moveRight(Node parent){
    currentBoard = parent.getState();
    Node result = new Node(parent);


    /* check you can move 'empty' right one space*/
    if(getemptyCol()  < 2){


        swapValues(result.getState(),emptyRow, emptyCol,2);



        return result;
    }

    return null;
}

   public void swapValues (char[][] c,int x, int y, int method){

    char empty = '0';
    char swapValue = '0'; // should never be kept as 0

    if(method == 1){ // left

        swapValue= c[emptyRow][emptyCol -1];
        c[emptyRow][emptyCol] = swapValue;
        c[emptyRow][emptyCol -1] = empty;
        trackEmptySqaure();


    }
    else if(method == 2){ // down

        swapValue = c[emptyRow + 1][emptyCol];
        c[emptyRow][emptyCol] = swapValue;
        c[emptyRow + 1][emptyCol] = empty;
        trackEmptySqaure();


    }
    else if(method == 3){ // up
        swapValue = c[emptyRow -1][emptyCol];
        c[emptyRow][emptyCol] = swapValue;
        c[emptyRow -1][emptyCol] = empty;
        trackEmptySqaure();


    }
    else if(method == 4){// right
        swapValue = c[emptyRow][emptyCol + 1];
        c[emptyRow][emptyCol] = swapValue;
        c[emptyRow ][emptyCol + 1] = empty;
        trackEmptySqaure();


    }




}
public class DFSSolver {

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

private Stack<Node> open = new Stack<Node>();

private PuzzleBoard pb;

private boolean solved;

private int numberOfSteps;

public DFSSolver(PuzzleBoard puzzle) {

    pb = puzzle;
    numberOfSteps = 0;
    solved = false;
    Node root = new Node();
    root.setState(pb.getCurrentBoard());
    addToOpen(root);
    checkIfSolved(root);
    search();

}

public boolean inOpenList(Node n){

    for(Node node: open){
        if(node.equals(n)){
            return true;
        }

    }
    return false;

}

public boolean inClosedList(Node n){

    for(Node node: closed){
        if(node.equals(n)){
            return true;
        }

    }
    return false;

}


public void addToOpen(Node n){
    open.push(n);
}

public void addToClosed(Node n){
    closed.add(n);

}

public Node popOpen(){
    return open.pop();
}

public void removeFromClosed(Node n){

    closed.remove(n);

}



public void search(){

    while(!solved){

        Node current = popOpen();
        if(current != null){
            if(!(inClosedList(current))){ // is it previously explored?
                checkIfSolved(current);
                addChildren(current);
                numberOfSteps++;

            }

            addToClosed(current);
        }
    }
    System.out.println("No of steps: " + numberOfSteps);
}

public void checkIfSolved(Node curr) {
    char[][] goal = pb.getGoal();
    char[][] current = curr.getState();
    for(int i = 0; i < 3; i ++){
        for(int j = 0; j < 3; j ++){
            char c = current[i][j];
            char x = goal[i][j];
            if(c != x){
                return;
            }
        }
    }

    solved = true;
}


public void addChildren(Node parent){


    Node newNode = new Node(parent);



    newNode = pb.moveLeft(parent);

    if(newNode != null){
        System.out.println("Parent: " + parent.getState().toString());
        System.out.println("atfer moving left");
        System.out.println(newNode.toString());
        addToOpen(newNode);


    }

    newNode = pb.moveDown(parent);

    if(newNode != null){
        System.out.println("Parent: " + parent.getState().toString());
        System.out.println("atfer moving down");
        System.out.println(newNode.toString());
        addToOpen(newNode);


    }


    newNode = pb.moveRight(parent);

    if(newNode != null){
        System.out.println("Parent: " + parent.getState().toString());
        System.out.println("atfer moving right");
        System.out.println(newNode.toString());
        addToOpen(newNode);


    }


    newNode = pb.moveUp(parent);

    if(newNode != null){
        System.out.println("Parent:\n " + parent.toString());
        System.out.println("atfer moving up");
        System.out.println(newNode.toString());
        addToOpen(newNode);


    }
}
4

2 回答 2

0

move up你这样调用的方法中swap values

swapValues(result.getState(),emptyRow, emptyCol,2);

但我想应该是:

swapValues(result.getState(),emptyRow, emptyCol,3);

你也想打电话:

swapValues(result.getState(),emptyRow, emptyCol,4);

在你的moveRight方法中

于 2013-10-31T18:42:29.213 回答
0

I believe the other problem you reported is because the code's notion of where the empty square is doesn't always match the node you are currently processing. You call trackEmptySquare after each swap, but a better place would be to call it at before moveLeft, moveRight, etc., so that it will match the node you are currently looking at.

But the better approach would be to get rid of the variables that track the empty row and col. Each Node has its own empty square. You can either move the empty-row/empty-col variables into the Node class, and update them every time the Node's state changes. Or don't add them at all, just add a method that searches Node.state for the empty square.

于 2017-04-28T14:00:33.867 回答