1

I am trying to write a sudoku solver with backtracking right now and I solved some problems already but I don't know what to do now.

This is the Problem:

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)

When I run the code

I don't expect to get the right code handed to me, i just appreciate every help.

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);
    }
}
Jud
  • 1,324
  • 3
  • 24
  • 47
Akyro
  • 11
  • 2

2 Answers2

2

Without a line number in the exception, I'm going to blame the i in the second loop conditional in containedin3x3. The body never changes i, so j gets incremented until it goes out of bounds.

for(int i = firstRow; i < firstRow+3; i++){
  for(int j = firstCol; i < firstCol+3; j++){
Thomas
  • 5,074
  • 1
  • 16
  • 12
0

The stack trace in the image you linked appears to implicate this line:

    return sudokuboard[i][j];

The error message indicates that the value of the out-of-bounds index is 9.

Supposing that you are solving a 9x9 sudoku, variable sudokuboard will have dimensions 9, 9. In Java, array indices start at 0, so the valid range for both indexes of that array is 0 to 8.

It would take rather more analysis on my part to work out why that method is called with incorrect arguments, as it is; that job would better be handled via a debugger.

Update:

seems to be the problem but i dont know how to change it

Generally speaking, "knowing how to change it" depends on determining just where and how things go pear-shaped. That is one of the things a debugger is useful for, as I already suggested. You really should learn how to use one.

The rest of the stack trace can be useful for that purpose as well. In this case, it implicates this method invocation on line 10 of BacktrackingISudokuSolver.backtracking():

containedinRoC(sudoku,row,i,number)

It doesn't take much study of the code to conclude that the only argument that could be out of bounds is row, whose value was itself an argument to a recursive call to backtracking() at line 19 (referring again to the stack trace). Consider, then, that line and the ones around it:

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        }

Looking at that code, and at line 19 in particular, do you see any way that this method could have been called with valid arguments, yet perform a recursive call with invalid arguments? That's what you need to fix.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157