i have a problem with my program, it should solve the sudoku and print when its done, but the problem is, the program looks like it never ends, after printing the solved sudoku it gets errors.
here is the loop which is the program is making:
It also doesn't print field when it should, if i remove the System.out.print(f+"\n");
at start it prints nothing just errors.
Code:
public class Sudoku {
public static void main(String[] args) throws SolvedException {
Field field = new Field();
field.fromFile("test1.txt");
SudokuSolver solver = new SudokuSolver();
solve(field, 0, 0, solver);
System.out.println(field);
}
public static void solve(Field f, int i, int j, SudokuSolver solver) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
solver.done=true;
return;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
solve (f, i+1, 0, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
} else {
solve(f,i,j+1, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
solve(f,i+1,0, solver);
} else {
solve(f,i,j+1, solver);
}
}
}
SudokuSolver
public class SudokuSolver{
/* Set true when the solve is done */
public boolean done;
}
errors:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at Field.isEmpty(Field.java:101)
at Sudoku.solve(Sudoku.java:30)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.main(Sudoku.java:9)
Any ideas how could i stop the loop and print the right field? System.out.println(field)
instead of this one in solve method?
Recursion that never terminates
(In this case, it does terminate when it errors).
This part of your code needs to actually do something to indicate that it's done:
Otherwise that loop simply continues going, unaware that it should've stopped (shortened):
So, based on
throws SolvedException
your code should throw an exception there:But this is a Bad Idea. Exceptions are not for controlling code flow - they are for completely unexpected situations.
Signalling that it's done
Instead, we need to have some way of knowing when the code has reached that 'done' condition. In classic recursion, this is performed by returning something. As we want to know only if it's done or not, a
bool
handles that fine:In the callee, you also have this:
Which you would also swap out for:
Returning void instead
You mentioned that you'd still like to return
void
. Ok, so, we'll need to track that 'done' state somewhere else - e.g. inside some object which we'll callSudokuSolver
:Using that makes the code look more like this instead:
With the call site now looking like this: