线程主java.lang.arrayindexoutofboundsexception中的java异常9

时间:2015-04-20 18:36:49

标签: java backtracking

我正在努力编写一个带有回溯的数独求解器,我已经解决了一些问题,但我现在还不知道该做什么。

这就是问题:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at ISudoku.NumberOnBoard(ISudoku.java:19)
at ISudokuSolver.containedinRoC(ISudokuSolver.java:23)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:10)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.backtracking(BacktrackingISudokuSolver.java:19)
at BacktrackingISudokuSolver.solveSudoku(BacktrackingISudokuSolver.java:4)
at Examples.main(Examples.java:17)

当我运行代码时

我不希望得到正确的代码交给我,我感谢你的帮助。

public class ISudoku {

    private boolean[][] sudokuboolean;
    private int[][] sudokuboard;
    private int size;


    public ISudoku(int size){
        this.size = size;
        sudokuboard = new int[size][size];
        sudokuboolean = new boolean[size][size];
    }

    public void setNumber(int i, int j, int number, boolean given){
        sudokuboard[i][j] = number;
        sudokuboolean[i][j] = given;
    }
    public int NumberOnBoard(int i, int j){
        return sudokuboard[i][j];
    }
    public int getSize(){
        return size;
    }

    public String toString(){
        String string = "";
        for(int i = 0; i < size; i++){
            for(int j = 0; j < size; j++){
                if(sudokuboolean[i][j]){
                    string += "<" + sudokuboard[i][j] + "> ";
                }
                else{
                    string += sudokuboard[i][j] + " ";
                }
                if(j == 2 || j == 5){
                    string += "  ";
                }
            }
            string += "\n";
            if(i == 2 || i == 5){
                string += "\n";
            }
        }

        return string;
    }
}
public abstract class ISudokuSolver {

    public abstract boolean solveSudoku(ISudoku sudoku);    

    public boolean containedin3x3(ISudoku sudoku,int row, int col, int value){
        int firstRow = row / 3 * 3;
        int firstCol = col / 3 * 3;

        for(int i = firstRow; i < firstRow+3; i++){
            for(int j = firstCol; j < firstCol+3; j++){
                if(!(i == row && j == col)){
                    if(sudoku.NumberOnBoard(i,j) == value){
                        return true;
                    }                   
                }
            }
        }
        return false;
    }
    public boolean containedinRoC(ISudoku sudoku,int row, int col, int value){
        for(int i = 0; i < 9;i++){
            if(i != col){
                if(sudoku.NumberOnBoard(row,i) == value){
                    return true;
                }
            }
            if(i != row){
                if(sudoku.NumberOnBoard(i,col) == value){
                    return true;
                }
            }
        }
        return false;
    }
}
public class BacktrackingISudokuSolver extends ISudokuSolver{

    public boolean solveSudoku(ISudoku sudoku){
        backtracking(0,1,sudoku);
        return true;
    }

    private boolean backtracking(int row,int number, ISudoku sudoku){
        for(int i = 0; i < sudoku.getSize();i++){
            if(!containedinRoC(sudoku,row,i,number) && !containedin3x3(sudoku,row,i,number)){
                sudoku.setNumber(row,i,number,false);
                if(row == sudoku.getSize()-1 && i == sudoku.getSize()-1 && number != 9){
                    number += 1;
                }
                if(row == sudoku.getSize()-1 && i == sudoku.getSize()-1 && number == 9){
                    return true;                        
                }
                else{
                    if(backtracking(row+1,number,sudoku)){
                        return true;
                    }
                    else{
                        sudoku.setNumber(row,i,0,false);
                    }
                }
            }
        }
        return false;
    }

}
public class Examples extends BacktrackingISudokuSolver {

    public static void main(String[] args) {


        ISudokuSolver solver = new BacktrackingISudokuSolver();
        ISudoku sudoku = new ISudoku(9);
        System.out.println(sudoku);
        System.out.println("Beispiel 1: ");
        System.out.println("Lösbar? (Erwartet): Ja");
        System.out.println("Benötigte Zeit? (Erwartet): 15 ms (Intel i5 3,8 Ghz)");
        long start = System.currentTimeMillis();
        boolean solvable = solver.solveSudoku(sudoku);

        long end = System.currentTimeMillis();
        System.out.println("Lösbar?: " + solvable);
        System.out.println("Benötigte Zeit: " + (end - start) + " ms");
        System.out.println(sudoku);
    }
}

2 个答案:

答案 0 :(得分:2)

在例外中没有行号,我会责怪i中第二个循环条件中的containedin3x3。正文永远不会更改i,因此j会递增,直到超出范围。

for(int i = firstRow; i < firstRow+3; i++){
  for(int j = firstCol; i < firstCol+3; j++){

答案 1 :(得分:0)

您链接的图片中的堆栈跟踪似乎暗示了这一行:

    return sudokuboard[i][j];

错误消息表明越界索引的值为9。

假设您正在解决9x9数独,变量sudokuboard将具有维度9,9。在Java中,数组索引从0开始,因此该数组的两个索引的有效范围是0到8。 / p>

我需要做更多的分析才能弄清楚为什么用不正确的参数调用该方法,因为它是;通过调试器可以更好地处理这项工作。

<强>更新

  

似乎是问题,但我不知道如何改变它

一般来说,“知道如何改变它”取决于确定事物在哪里以及如何变成梨形。正如我已经建议的那样,这是调试器有用的东西之一。你真的应该学习如何使用它。

堆栈跟踪的其余部分也可用于此目的。在这种情况下,它涉及BacktrackingISudokuSolver.backtracking()的第10行上的此方法调用:

containedinRoC(sudoku,row,i,number)

不需要对代码进行太多研究就可以得出结论,唯一可能超出范围的参数是row,其值本身就是对行backtracking()的递归调用的参数19(再次参考堆栈跟踪)。那么,考虑那条线及其周围的线:

09        for(int i = 0; i < sudoku.getSize();i++){
10            if(!containedinRoC(sudoku,row,i,number) && !containedin3x3(sudoku,row,i,number)){
11                sudoku.setNumber(row,i,number,false);
12                if(row == sudoku.getSize()-1 && i == sudoku.getSize()-1 && number != 9){
13                    number += 1;
14                }
15                if(row == sudoku.getSize()-1 && i == sudoku.getSize()-1 && number == 9){
16                    return true;                        
17                }
18                else{
19                    if(backtracking(row+1,number,sudoku)){
20                        return true;
21                    }
22                    else{
23                        sudoku.setNumber(row,i,0,false);
24                    }
25                }
26            }
27        }

查看该代码,特别是第19行,您是否看到过使用有效参数调用此方法的方法,但是使用无效参数执行递归调用?这就是你需要解决的问题。