Documente Academic
Documente Profesional
Documente Cultură
articles
quick answers
Sign in
discussions
community
help
CPOL
Rate this:
A Sudoku game written in Java which generates its own games on the fly.
Download Netbeans project - 36.8 KB
Download source - 8.9 KB
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 ...
Implementation
Model
The most important part of this application is in the Game class, which includes the following functionality:
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:
1. Check if a solution is found.
2. 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.
3. Y (of current field) is found by dividing the current index by the count of fields in a row.
4. An ArrayList is filled with the numbers 1 to 9 and shuffled. Shuffling is important because otherwise you always get the
same solution.
5. As long as there are numbers in the ArrayList, the following will be executed:
6.
1. 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.
2. Found number is placed on the current location.
3. The method is recursively called with an increase of the index, and the returning value is stored in a variable.
4. If this variable is not null, it is returned; otherwise, the current location is put back to 0 (meaning the field is a
blank).
int y = index / 9;
}
}
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.
1. A list is filled with all possible positions.
2. 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.
3. The list is passed to the method generateGame(int[][], List<Integer>) and the return value will be
returned.
2.
3.
4.
5.
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
passing an integer by reference, instead of by value.
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:
1. Check if a solution is found.
Found -> increase numberOfSolutions and return true if it equals 1; false otherwise.
Not found -> continue.
1. Get the next possible number. If the returned value equals -1, perform a break resulting a return of
true.
2. Set this number at current field.
3. 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.
False
1. Call this method recursively and instantly check against the returned value.
True -> continue (resulting in returning true).
4. Return true.
Hide Shrink
Copy Code
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);
}
} 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);
}
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 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
History
Initial release.
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.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
Share
Eric
Beijer
Sudoku Game in C#
Sudoku
y and x
Proj Folder
Re: SUDOKU
Buttons Disappear?
sudoku code
My vote of 5
Numbers to Letters
End results?
unable to run
Layout Normal
Per page 25
Update
Member 12381135
22-Mar-16 19:44
Member 12347332
23-Feb-16 16:09
Member 12176094
21-Dec-15 23:42
Member 12217597
19-Dec-15 5:20
Member 11760149
21-Jun-15 7:05
1-Oct-14 9:07
branoc
5-Apr-14 0:30
Member 10725055
4-Apr-14 7:36
Marco Giadone
24-Jan-14 4:51
Member 10427855
29-Nov-13 6:56
Member 10431549
27-Nov-13 23:30
ichsanelf
28-Nov-13 14:37
ichsanelf
27-Nov-13 20:50
Member 10427855
29-Nov-13 6:59
ichsanelf
29-Nov-13 15:11
CodeKing499
18-Jan-13 13:44
Sai Sathveer
26-Dec-12 4:57
Serhiy Perevoznyk
10-Oct-12 8:05
Yuwan Enginco
23-Sep-12 2:30
13-Sep-12 21:24
developer00
14-Sep-12 12:40
12-Sep-12 6:47
Eric Beijer
12-Sep-12 7:17
Member 8551910
9-Sep-12 7:21
Eric Beijer
News
Suggestion
Question
10-Sep-12 4:32
Refresh
Bug
Answer
Joke
Praise
1 2 Next
Rant
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160418.1 | Last Updated 18 Apr 2012
Admin