import java.util.ArrayList; import java.util.List; import java.util.Stack; public class SudokuSolver { private class Position { public int row; // note, given the simplicity of this inner Position class, we violate public int col; // our normal practice of keeping instance variables private public Position(int row, int col) { this.row = row; this.col = col; } } private class Choice { private int digit; /////////////////// // ADD CODE HERE // /////////////////// } private class State implements StateAllowingBacktracking { /////////////////// // ADD CODE HERE // /////////////////// public String toString() { final String CENTER_DOT = "\u00B7"; final String VERTICAL_LINE = "\u2503"; //(bold & covers entire width of char and horizontally centered) final String HORIZONTAL_LINE = "\u2501"; //(bold & covers entire height of char and vertically centered) final String VERT_HORIZ_CROSS = "\u254B"; //(bold & covers entire width and height of char and centered) // Note: if your terminal doesn't support colored text, try not to be too sad // and then change the next two strings to both be empty strings (i.e., "") final String ANSI_RESET = "\u001B[0m"; final String ANSI_CYAN = "\u001B[36m"; String s = ""; for (int r = 0; r < grid.length; r++) { for (int c = 0; c < grid[0].length; c++) { if (! editable[r][c]) s += ANSI_CYAN + grid[r][c] + ANSI_RESET; else s += (grid[r][c].digit != 0 ? grid[r][c] : CENTER_DOT); if (c == 2 || c == 5) s += VERTICAL_LINE; } if (r == 2 || r == 5) s += "\n" + HORIZONTAL_LINE + HORIZONTAL_LINE + HORIZONTAL_LINE + VERT_HORIZ_CROSS + HORIZONTAL_LINE + HORIZONTAL_LINE + HORIZONTAL_LINE + VERT_HORIZ_CROSS + HORIZONTAL_LINE + HORIZONTAL_LINE + HORIZONTAL_LINE; s += "\n"; } return s; } } int boardSize; StateAllowingBacktracking state; private Stack stackOfSolutions; int cnt = 0; public SudokuSolver(int[][] grid) { state = new State(grid); stackOfSolutions = new Stack(); } void searchFromCurrentState() { if (state.isSolution()) { //System.out.println("solution found!!"); reactToSolution(); return; // stop pursuing this path } for (Choice choice : state.nextChoicesToConsider()) { if (state.isValid(choice)) { state.makeChoice(choice); searchFromCurrentState(); // <-- the recursive call! state.undoChoice(choice); // try another path } } } public void reactToSolution() { stackOfSolutions.push(state.toString()); } public static void main(String[] args) { int[][] solvableGrid = {{0,3,9,0,0,0,7,0,0}, {0,0,0,7,0,0,1,0,0}, {6,0,0,0,8,0,0,0,4}, {8,0,4,0,0,7,0,0,6}, {0,0,0,8,0,0,4,0,0}, {0,5,0,2,0,6,8,1,0}, {0,0,0,0,0,0,0,7,0}, {5,8,0,0,0,3,9,4,0}, {7,2,3,4,0,8,6,0,0}}; SudokuSolver sudokuSolver = new SudokuSolver(solvableGrid); System.out.println("NEW PUZZLE:\n\n" + sudokuSolver.state); sudokuSolver.searchFromCurrentState(); System.out.println(sudokuSolver.stackOfSolutions.size() + " solutions(s) found:\n"); for ( String solution : sudokuSolver.stackOfSolutions) { System.out.println(solution); } System.out.println("-----------------\n"); int[][] unsolvableGrid = {{3,1,6,5,7,8,4,2,0}, {5,2,0,0,0,0,0,0,0}, {0,8,7,0,0,0,0,3,1}, {0,0,3,0,1,0,0,8,0}, {9,0,0,8,6,3,0,0,5}, {0,5,0,0,9,0,6,0,0}, {1,3,0,0,0,0,2,5,0}, {0,0,0,0,0,0,0,7,4}, {0,0,5,2,0,6,3,0,0}}; sudokuSolver = new SudokuSolver(unsolvableGrid); System.out.println("NEW PUZZLE:\n\n" + sudokuSolver.state); sudokuSolver.searchFromCurrentState(); System.out.println(sudokuSolver.stackOfSolutions.size() + " solutions(s) found:\n"); for ( String solution : sudokuSolver.stackOfSolutions) { System.out.println(solution); } } }