I did this Sudoku solver for a school project and I’ve now decided to release it as a proof-of-concept project. It’s nothing fancy. It contains a class used to brute force Sudoku puzzles, you can read more about the algorithm on Wikipedia, and a little Swing GUI. I’ve never used Swing before doing this project so don’t expect anything amazing. The code is released under GPL v2 and I hope it might be useful to someone out there. There is a generated Javadoc so check it out for more detailed info about the classes.
Check out the code in my public Mercurial repository.
And heres a overview of the brute force class (got to the Mercurial repository to get the GUI source):
/**
* Sudoku Solver Proof-of-concept.
* Copyright (C) 2011 Anton Fagerberg (Kung Foo Code).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package sudoku;
public class Sudoku {
private int[][] matrix = new int[9][9];
private int[][] inputMatrix = new int[9][9];
/**
* Remove all the numbers from the sudoku-matrixes.
*/
public void resetMatrix() {
matrix = new int[9][9];
inputMatrix = new int[9][9];
}
/**
* Set value of the X- & Y-coordinate in the matrix.
* If x > 8 the y-value will automatically increase. set(0, 1, 1) is the same as set(9, 0, 1).
* @param x X-coordinate, 0-80.
* @param y Y-coordinate, 0-8.
* @param value Number, 1,9.
*/
private void fill(int x, int y, int value) {
while (x < 0) {
x += 9;
y--;
}
while(x > 8) {
x -= 9;
y++;
}
matrix[x][y] = value;
}
/**
* Save value from user input to the matrix which handles user input.
* If x > 8 the y-value will automatically increase. set(0, 1, 1) is the same as set(9, 0, 1).
* @param x X-coordinate, 0-80.
* @param y Y-coordinate, 0-8.
* @param value Number, 1,9.
*/
public void set(int x, int y, int value) {
while (x < 0) {
x += 9;
y--;
}
while(x > 8) {
x -= 9;
y++;
}
inputMatrix[x][y] = value;
}
/**
* Copy the values of the matrix containing the user input to the matrix used when trying to solve the puzzle.
*/
private void copyMatrix() {
for (int x = 0; x != 9; x++)
for (int y = 0; y != 9; y++)
matrix[x][y] = inputMatrix[x][y];
}
/**
* Try to solve the sudoku-puzzle.
* @return True or false based on if the puzzle was solved or not.
*/
public boolean solve() {
copyMatrix();
return solve(0);
}
/**
* Get the value from the specified X- & Y-coordinate in the matrix used to solve the sudoku-puzzles.
* If x > 8 the y-value will automatically increase. set(0, 1, 1) is the same as set(9, 0, 1).
* @param x X-coordinate, 0-80.
* @param y Y-coordinate, 0-8.
* @return The value, 0-9. (0 is regarded as not defined).
*/
public int getValue(int x, int y) {
while (x < 0) {
x += 9;
y--;
}
while(x > 8) {
x -= 9;
y++;
}
return matrix[x][y];
}
/**
* Get the value from the specified X- & Y-coordinate from the matrix which contain the user inputs.
* If x > 8 the y-value will automatically increase. set(0, 1, 1) is the same as set(9, 0, 1).
* @param x X-coordinate, 0-80.
* @param y Y-coordinate, 0-8.
* @return The value, 0-9. (0 is regarded as not defined).
*/
public int getValueOriginal(int x, int y) {
while (x < 0) {
x += 9;
y--;
}
while(x > 8) {
x -= 9;
y++;
}
return inputMatrix[x][y];
}
/**
* Recursive function which fills a valid number to the X- & Y-coordinate based on the sudoku-rules.
* The function will call itself with the next X- & Y-coordinate if it finds a valid number to insert or if the number is already set by the user input.
* If x > 8 the y-value will automatically increase.
* @param x X-coordinate.
* @return True or false if a valid number can be inserted or not.
*/
private boolean solve(int x) {
if (x == 81)
return true;
if (getValue(x, 0) != 0 && getValue(x, 0) == getValueOriginal(x, 0)) {
return solve(x+1);
}
else {
for (int i : getValidNumbers(x, 0)) {
if (i != 0) {
fill(x, 0, i);
if (!solve(x+1))
fill(x,0,0);
else
return true;
}
}
}
return false;
}
/**
* Validate if a specified number is valid at the X- & Y-coordinate based on the sudoku-rules.
* If x > 8 the y-value will automatically increase. set(0, 1, 1) is the same as set(9, 0, 1).
* @param x X-coordinate, 0-80.
* @param y Y-coordinate, 0-8.
* @param number Number (Only 1-9 can be valid).
* @return True or false based on if the number is valid according to the sudoku-rules.
*/
public boolean validNumberOriginal (int x, int y, int number) {
if (number < 1 || number > 9)
return false;
while (x < 0) {
x += 9;
y--;
}
while(x > 8) {
x -= 9;
y++;
}
int[] validNumbers = {1,2,3,4,5,6,7,8,9};
// Check vertical and horizontal
for (int i = 0; i != 9; i++) {
if (inputMatrix[i][y] != 0)
validNumbers[inputMatrix[i][y]-1] = 0;
if (inputMatrix[x][i] != 0)
validNumbers[inputMatrix[x][i]-1] = 0;
}
// Check the "squares"
int squareX, squareY;
if (x < 3)
squareX = 0;
else if (x < 6)
squareX = 3;
else
squareX = 6;
if (y < 3)
squareY = 0;
else if (y < 6)
squareY = 3;
else
squareY = 6;
for (int i = 0; i != 3; i++) {
for (int j = 0; j != 3; j++) {
if (inputMatrix[i+squareX][j+squareY] != 0) {
validNumbers[inputMatrix[i+squareX][j+squareY]-1] = 0;
}
}
}
return (validNumbers[number-1] == 0) ? false : true;
}
/**
* Returns an array of the valid numbers at the X- & Y-coordinate according to the sudoku-rules.
* If the number n is valid the array will have array[n-1] = n. If n is invalid array[n-1] = 0.
* If x > 8 the y-value will automatically increase. set(0, 1, 1) is the same as set(9, 0, 1).
* @param x X-coordinate, 0-80.
* @param y Y-coordinate, 0-8.
* @return Array of valid numbers (size 9).
*/
private int[] getValidNumbers(int x, int y) {
while (x < 0) {
x += 9;
y--;
}
while(x > 8) {
x -= 9;
y++;
}
int[] validNumbers = {1,2,3,4,5,6,7,8,9};
// Check vertical and horizontal
for (int i = 0; i != 9; i++) {
if (matrix[i][y] != 0) {
validNumbers[matrix[i][y]-1] = 0;
}
if (matrix[x][i] != 0) {
validNumbers[matrix[x][i]-1] = 0;
}
}
// Check the "squares"
int squareX, squareY;
if (x < 3)
squareX = 0;
else if (x < 6)
squareX = 3;
else
squareX = 6;
if (y < 3)
squareY = 0;
else if (y < 6)
squareY = 3;
else
squareY = 6;
for (int i = 0; i != 3; i++) {
for (int j = 0; j != 3; j++) {
if (matrix[i+squareX][j+squareY] != 0) {
validNumbers[matrix[i+squareX][j+squareY]-1] = 0;
}
}
}
return validNumbers;
}
/**
* Print a ascii-version of the sudoku-puzzle to the console.
*/
public void printTable() {
System.out.print("\n");
for (int x = 0; x != 9; x++) {
for (int y = 0; y != 9; y++) {
System.out.print(" " + inputMatrix[x][y] + " ");
if (y == 2 || y == 5)
System.out.print("|");
}
if (x == 2 || x == 5)
System.out.print("\n---------+---------+--------");
System.out.print("\n");
}
}
}

how much time it takes to solve different number of hints of grid
It doesn’t really matter how many hints you have since backtracking is used. What matters more is which hints are on which locations. You can check out the Wikipedia link in my post about the algorithm for more information about how to create the hardest possible solution for the algorithm to solve. You can’t however copy the one from Wikipedia since my algorithm move up to down and not left to right. Also the computers performance also has to be taken in to account.
The GUI has a built in timer so you can do some benchmarks if you like. Feel free to ask more if you’re interested!
Are there any instructions on how to compile and run the project?
Late reply but the simplest way is to just download the .jar file and execute it. The way you should do this depends on which operating system you are using.
If you want compile it one Unix you can do something like this:
Optional 1: clone repository: hg clone http://code.kungfoocode.org/Sudoku/ (or get it manually)
1. cd into the base dir “Sudoku”
2. javac -d . src/sudoku/Layout.java src/sudoku/Sudoku.java
3. jar cf sudoku.jar sudoku/
4. java -cp sudoku.jar sudoku.Layout