I'm making a SudokuSolver for a class, and I'm having trouble with the solve method. My current solution uses recursive backtracking (I think).
Assignment Requirements
int solve() -- tries to solve the puzzle using the strategy described above. Returns the number of solutions.
(The strategy described above)
When assigning a number to a spot, never assign a number that, at that moment, conflicts with the spot's row, column, or square. We are up-front careful about assigning legal numbers to a spot, rather than assigning any number 1..9 and finding the problem later in the recursion. Assume that the initial grid is all legal, and make only legal spot assignments thereafter.
Pseudocode Idea
I can follow this iteratively for a small input. For example, say I have to unsolved cells Cell #1 and Cell #2. #1 has possibilities { 1, 3 } and #2 has possibilities { 2, 3 }. I would then
set 1 to 1
set 2 to 2
hasConflicts? 0 : 1
set 2 to 3
hasConflicts? 0 : 1
set 1 to 3
set 2 to 2
hasConflicts? 0 : 1
set 2 to 3
hasConflicts? 0 : 1
Actual Code
public int solve() {
long startTime = System.currentTimeMillis();
int result = 0;
if (!hasConflicts()) {
Queue<VariableCell> unsolved = getUnsolved();
reduceUnsolvedPossibilities(unsolved); // Gets the possibilities down from all of 1-9
if (!hasConflicts()) {
result = solveRec(unsolved);
}
}
mElapsedTime = System.currentTimeMillis() - startTime;
return result;
}
protected int solveRec(Queue<VariableCell> unsolved) {
if (unsolved.isEmpty()) {
return (hasConflicts()) ? 0 : 1;
}
int result = 0;
VariableCell cell = unsolved.remove();
Iterator<String> possibilityIt = cell.getPossibilities().iterator();
while (possibilityIt.hasNext()) {
cell.setSymbol(possibilityIt.next());
if (hasConflicts()) {
possibilityIt.remove();
} else {
++result;
}
}
return result + solveRec(unsolved);
}
Test Results
testSolveSingleSolution
expected 1, actual 1
testSolveSolved
expected 1, actual 1
testSolveUnsolvable
expected 0, actual 0
testSolveMultiSolutions
expected 2, actual 7 // MAJOR PROBLEM!
Some Good Explanations of Recursive Backtracking
- This answer to StackOverflow - Recursive solution to Sudoku generator
- This answer to StackOverflow - BackTracking in a maze
- This answer to StackOverflow - Backtracking algorithm for prime sequence
- This answer to StackOverflow - How to find the first solution only with this backtracking
- The Wikipedia article on Backtracking
- Recursive Backtracking Explanation
Question
I've done recursive backtracking before, I've looked at all those links above and more, and I'm still having trouble. I think the problem lies in my thinking about how to solve this. (See Pseudocode Idea.) Is it appropriate to use recursive backtracking for an exhaustive search? Is the backtracking right but the implementation wrong? Is there a better algorithm I can use than recursive backtracking?