I am implementing recursive backtracking algorithm for sudoku. Below is the code to create board with random filling. I wonder if I can make it better in any terms of readable coding especially validation methods. in Board class.
public class Board {
private int[][] board;
public final static int SIZE = 9;
public Board() {
create();
}
public int[][] getBoard() {
return board;
}
private void create() {
int openspots = 20;
board = new int[SIZE][SIZE];
Random rand = new Random();
int random, randomrow, randomcolumn;
while (openspots-- > 0) {
random = rand.nextInt(SIZE) + 1;
randomrow = rand.nextInt(SIZE);
randomcolumn = (rand.nextInt(SIZE));
if (board[randomrow][randomcolumn] == 0) {
board[randomrow][randomcolumn] = random;
int count = 0;
while (!isValid(randomrow, randomcolumn)) {
if (count++ == 9) {
board[randomrow][randomcolumn] = 0;
openspots++;
break;
}
random = rand.nextInt(SIZE) + 1;
board[randomrow][randomcolumn] = random;
}
}
}
}
public void printBoard() {
for (int row = 0; row < SIZE; row++) {
for (int column = 0; column < SIZE; column++) {
System.out.print(board[row][column] + " ");
}
System.out.println();
}
}
public boolean isValid(int row, int column) {
return isValidRow(row) && isValidColumn(column) && isValidBlock(row, column);
}
private boolean isValidRow(int row) {
if (row > 8 || row < 0)
throw new IllegalArgumentException("Row must be between 0 and " + (SIZE - 1) + " inclusive!");
Set<Integer> set = new HashSet<>();
for (int i = 0; i < SIZE; i++) {
if (board[row][i] != 0 && set.contains(board[row][i])) {
return false;
} else {
set.add(board[row][i]);
}
}
return true;
}
private boolean isValidColumn(int column) {
if (column > 8 || column < 0)
throw new IllegalArgumentException("Column must be between 0 and " + (SIZE - 1) + " inclusive!");
Set<Integer> set = new HashSet<>();
for (int i = 0; i < SIZE; i++) {
if (board[i][column] != 0 && set.contains(board[i][column])) {
return false;
} else {
set.add(board[i][column]);
}
}
return true;
}
private boolean isValidBlock(int row, int column) {
if (column > 8 || column < 0)
throw new IllegalArgumentException("Column must be between 0 and " + (SIZE - 1) + " inclusive!");
int blockrow = (row / 3) * 3;
int blockcolumn = (column / 3) * 3;
Set<Integer> set = new HashSet<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[blockrow + i][blockcolumn + j] != 0 && set.contains(board[blockrow + i][blockcolumn + j])) {
return false;
} else {
set.add(board[blockrow + i][blockcolumn + j]);
}
}
}
return true;
}
}
The one below is the solver class which has the main algorithm to solve sudoku.
public class Solver {
public boolean solve(Board board) {
int[][] boardarr = board.getBoard();
for (int i = 0; i < board.SIZE; i++) {
for (int j = 0; j < board.SIZE; j++) {
if (boardarr[i][j] == 0) {
for (int k = 1; k <= board.SIZE; k++) {
boardarr[i][j] = k;
if (board.isValid(i,j) && solve(board)) {
return true;
}
boardarr[i][j] = 0;
}
return false;
}
}
}
return true;
}
}