package sudoku; public class Solver implements SudokuSolver { private int[][] board = null; public Solver() { board = new int[9][9]; } public void setBoard(int[][] board) { this.board = board; } public int[][] getBoard() { return board; } /** * Resets the board to all zeros */ public void reset() { board = new int[9][9]; } public boolean solve() { return solve(0, 0); } /** * Recursive helper method for solve() * * @param row row to solve * @param col column to solve * @return true if solved */ private boolean solve(int row, int col) { if (row < 0 || row > 9 || col < 0 || col > 9) { return false; } if (row == 9) { row = 0; if (++col == 9) { return true; } } if (board[row][col] != 0) { return solve(row + 1, col); } for (int val = 1; val <= 9; ++val) { if (legal(row, col, val)) { board[row][col] = val; if (solve(row + 1, col)) { return true; } } } board[row][col] = 0; return false; } /** * Randomizes the board. This guarantees a solvable board. */ public void randomizeBoard() { this.reset(); for (int i = 0; i < 9; ++i) { int row = (int) (Math.random() * 9); int col = (int) (Math.random() * 9); int val = (int) (Math.random() * 9) + 1; if (legal(row, col, val)) { board[row][col] = val; } } } /** * Sets the value of the board at the given position * * @param row row to set * @param col column to set * @param val value to set */ public void setPos(int row, int col, int val) { if (row < 9 && col < 9) { board[row][col] = val; } } /** * Checks if val is legal in the given row, column, and 3x3 box * * @param row row to check * @param col column to check * @param val value to check * @return true if val is legal */ public boolean legal(int row, int col, int val) { if (row < 0 || row >= 9 || col < 0 || col >= 9 || val < 1 || val > 9) { return false; } // Check if val is already in col for (int i = 0; i < 9; ++i) { if (val == board[i][col]) { return false; } } // Check if val is already in row for (int j = 0; j < 9; ++j) { if (val == board[row][j]) { return false; } } // Check the 3x3 box int boxRowOffset = (row / 3) * 3; int boxColOffset = (col / 3) * 3; for (int k = 0; k < 3; ++k) { for (int m = 0; m < 3; ++m) { if (val == board[boxRowOffset + k][boxColOffset + m]) { return false; } } } // None of the above failed, so it is legal return true; } public boolean isSolved() { return isSolved(0, 0); } /** * Recursive helper method for isSolved() * * @param row * @param col * @return */ private boolean isSolved(int row, int col) { // If we are at the 9th row and 0th column (the last cell), we are done if (row == 9) { row = 0; if (++col == 9) { return true; } } // If we find a zero, the board is not solved if (board[row][col] == 0) { return false; } for (int i = 0; i < 9; ++i) { // Checks if there is a duplicate in the row if (i != row && board[i][col] == board[row][col]) { return false; } // Checks if there is a duplicate in the column if (i != col && board[row][i] == board[row][col]) { return false; } } // Checks if there is a duplicate in the 3x3 box int boxRowOffset = (row / 3) * 3; int boxColOffset = (col / 3) * 3; for (int k = 0; k < 3; ++k) { for (int m = 0; m < 3; ++m) { int r = boxRowOffset + k; int c = boxColOffset + m; if ((r != row || c != col) && board[r][c] == board[row][col]) { return false; } } } return true; } /** * Returns a string representation of the board * * @return String representation of the board */ // Not particularly pretty, but it works public String toString() { final String divider = "-------+--------+--------\n"; StringBuilder sb = new StringBuilder(); sb.append(divider); int rowcount = 0; for (int[] row : board) { int colcount = 0; sb.append("| "); for (int val : row) { colcount++; sb.append(val); sb.append(colcount % 3 == 0 ? " | " : " "); } rowcount++; sb.append(rowcount % 3 == 0 ? "\n" : ""); sb.append(rowcount % 3 == 0 ? divider : "\n"); } return sb.toString(); } }