我正在努力编写一个带有回溯的数独求解器,我已经解决了一些问题,但我现在还不知道该做什么。
这就是问题:
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);
}
}
答案 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行,您是否看到过使用有效参数调用此方法的方法,但是使用无效参数执行递归调用?这就是你需要解决的问题。