## Introduction

This article is on the implementation of a Sudoku game in Java. This version includes an intuitive interface with the ability to use help and to check for errors. Turning on help will mark all possible fields for the selected number. After checking for errors, the program marks valid fields green and invalid fields red. The rules used in this implementation are as follows:

- An integer may only appear once in ...
- ... the same row.
- ... the same column.
- ... the same 3x3 region.

- A game has only one solution.

## Implementation

### Model

The most important part of this application is in the `Game`

class, which includes the following functionality:

- Generate a new solution;
- Generate a new game from a solution;
- Keep track of user input;
- Check user input against generated solution;
- Keep track of selected number;
- Keep track of help is on or off.

Because the `Game`

class extends `Observable`

, it can and does notify observers when certain changes have been performed. This particular application contains two observers, `ButtonPanel`

and `SudokuPanel`

. When the `Game`

class executes `setChanged()`

followed by `notifyObservers(...)`

, the observers will execute their `update(...)`

method.

Besides the `Game`

class, the model consists of an enumeration called `UpdateAction`

which will tell observers what kind of update has taken place.

#### Generate Solution

Before we can start generating a game, we must first generate a solution. This is achieved by the method below, which needs to be called by the user as `generateSudoku(new int[9][9], 0)`

. The following steps are taken:

- Check if a solution is found.
- Found -> solution is returned.
- Not found -> continue.

- X (of current field) is found by finding the remainder of the division of the current index by the count of fields in a row using the modulo operation.
- Y (of current field) is found by dividing the current index by the count of fields in a row.
- An
`ArrayList`

is filled with the numbers 1 to 9 and shuffled. Shuffling is important because otherwise you always get the same solution. - As long as there are numbers in the
`ArrayList`

, the following will be executed:
- The next possible number is obtained by the method
`getNextPossibleNumber(int[][], int, int, List<Integer>)`

, which will be explained later on. If there's no next possible number (return value of -1), `null`

is returned. - Found number is placed on the current location.
- The method is recursively called with an increase of the index, and the returning value is stored in a variable.
- If this variable is not
`null`

, it is returned; otherwise, the current location is put back to 0 (meaning the field is a blank).

`null`

is returned. This part will never be reached, hopefully.

private int[][] generateSolution(int[][] game, int index) {
if (index > 80)
return game;
int x = index % 9;
int y = index / 9;
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i <= 9; i++)
numbers.add(i);
Collections.shuffle(numbers);
while (numbers.size() > 0) {
int number = getNextPossibleNumber(game, x, y, numbers);
if (number == -1)
return null;
game[y][x] = number;
int[][] tmpGame = generateSolution(game, index + 1);
if (tmpGame != null)
return tmpGame;
game[y][x] = 0;
}
return null;
}

As previously said, the method `getNextPossibleNumber(int[][], int, int, List<Integer>)`

is used for obtaining the next possible number. It takes a number from the list and checks whether it is possible at the given x and y position in the given game. When found possible, the number is returned. If the list is empty and thus no number is possible at this location, -1 is returned.

private int getNextPossibleNumber(int[][] game, int x, int y, List<Integer> numbers) {
while (numbers.size() > 0) {
int number = numbers.remove(0);
if (isPossibleX(game, y, number)
&& isPossibleY(game, x, number)
&& isPossibleBlock(game, x, y, number))
return number;
}
return -1;
}

#### Generate Game

Generating a game is simply achieved by constantly removing a random field and making sure the game is still valid. Valid means there is only one solution. This is achieved by the methods below. The user should call the first method, which uses the second method. I will describe the steps again.

- A list is filled with all possible positions.
- The list is shuffled. I do not know why. I suspect that this way, the blanks are better distributed. With the result that the game is harder.
- The list is passed to the method
`generateGame(int[][], List<Integer>)`

and the return value will be returned.

private int[][] generateGame(int[][] game) {
List<Integer> positions = new ArrayList<Integer>();
for (int i = 0; i < 81; i++)
positions.add(i);
Collections.shuffle(positions);
return generateGame(game, positions);
}

- As long as there are positions in the list, the following will be executed:
- A position is taken from the list and stored in a variable.
- x and y are calculated from this position.
- Value at this position is stored in the variable
`temp`

. - Value at this position is set to 0 (meaning the field is a blank).
- This step is critical. As the removal of the value at the position means that the game is no longer valid, the value at the position is put back. Otherwise the game stays the same.

- The game is returned.

private int[][] generateGame(int[][] game, List<Integer> positions) {
while (positions.size() > 0) {
int position = positions.remove(0);
int x = position % 9;
int y = position / 9;
int temp = game[y][x];
game[y][x] = 0;
if (!isValid(game))
game[y][x] = temp;
}
return game;
}

As you can see, this method is used to pass default values. So why the `new int[] { 0 }`

? This is the most common way of passing an integer by reference, instead of by value.

private boolean isValid(int[][] game) {
return isValid(game, 0, new int[] { 0 });
}

A valid game has in every row, every column, and every region the numbers 1 to 9. Additionally, there should only be one solution existing. To achieve this, all open fields are filled with the first valid value. Even after finding a solution, the search continues by putting the next valid value in an open field. If a second solution is found, then the search will be stopped and the method returns `false`

. There will always be at least one solution (hence `game`

is an incomplete solution), so if there are less than two solutions, the game is valid and the method returns `true`

. Step by step:

- Check if a solution is found.
- Found -> increase
`numberOfSolutions`

and return `true`

if it equals 1; `false`

otherwise. - Not found -> continue.

- Calculate x and y from index.
- Check if current field is a blank (equals 0).
- True
- Fill a list with numbers 1 to 9.
- While the list contains numbers, execute the following:
- Get the next possible number. If the returned value equals -1, perform a break resulting a return of
`true`

. - Set this number at current field.
- Call this method recursively and instantly check against the returned value.
- True -> one or no solution found, continue search.
- False -> more than one solution found, stop searching. Restore game and return
`false`

.

- Restore value of current field to 0 (meaning it is blank).

- False
- Call this method recursively and instantly check against the returned value.
- True -> continue (resulting in returning
`true`

). - False -> return
`false`

.

- Return
`true`

.

private boolean isValid(int[][] game, int index, int[] numberOfSolutions) {
if (index > 80)
return ++numberOfSolutions[0] == 1;
int x = index % 9;
int y = index / 9;
if (game[y][x] == 0) {
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i <= 9; i++)
numbers.add(i);
while (numbers.size() > 0) {
int number = getNextPossibleNumber(game, x, y, numbers);
if (number == -1)
break;
game[y][x] = number;
if (!isValid(game, index + 1, numberOfSolutions)) {
game[y][x] = 0;
return false;
}
game[y][x] = 0;
}
} else if (!isValid(game, index + 1, numberOfSolutions))
return false;
return true;
}

#### Check Game

With checking user input, we compare each field in the game against the corresponding field in the solution. The result is stored in a two dimensional boolean array. The selected number is also set to 0 (meaning no number is selected). All observers are notified that the model has changed with the corresponding `UpdateAction`

.

public void checkGame() {
selectedNumber = 0;
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
check[y][x] = game[y][x] == solution[y][x];
}
setChanged();
notifyObservers(UpdateAction.CHECK);
}

### View & Controller

There is not much to say about the view part, only the structure of the panels. The controllers react to user input and implement changes to the model. The model notifies it has been changed. The view responses to this notification and updates. These updates of the view are limited to changing colors and changing the number of a field. There is no rocket science involved.

#### Sudoku

The view also is the entry point of this application; the `Sudoku`

class contains the main method. This class builds up the user interface by creating a `JFrame`

and placing `SudokuPanel`

and `ButtonPanel`

inside this frame. It also creates the `Game`

class, and adds `SudokuPanel`

and `ButtonPanel`

as observers to it.

#### SudokuPanel and Fields

`SudokuPanel`

contains 9 sub panels each containing 9 fields. All sub panels and fields are placed in a `GridLayout`

of 3x3. Each sub panel represents a region of a Sudoku game, and is primarily used for drawing a border visually separating each region. They also get the `SudokuController`

added to them, which is in charge of processing user input by mouse.

#### ButtonPanel

`ButtonPanel`

contains two panels with a titled border. The first panel contains three buttons. Button New for starting a new game, button Check for checking user input, and button Exit for exiting the application. The second panel contains 9 toggle buttons placed inside a button group. This way, they react like radio buttons. Clicking one of these toggle buttons will set the corresponding selected number in the `Game`

class.

## Points of Interest

- For passing an integer by reference instead of by value, use an integer array.

isValid(game, 0, new int[] { 0 });
private boolean isValid(int[][] game, int index, int[] numberOfSolutions);

Finding the base x and y values of a region, use the following:
int x1 = x < 3 ? 0 : x < 6 ? 3 : 6;
int y1 = y < 3 ? 0 : y < 6 ? 3 : 6;

## History

## Apologies

One, if I have driven you mad with my bad English, I apologize. Two, if I have driven you mad before because usually my source doesn't contain comments, I apologize, and I can tell you, in this case, it does. Not because I acknowledge their usefulness, but to avoid discussions. Three, if I didn't mention before that you can use your right mouse button to clear a field, I apologize.