Sudoku Solver Using Threads in Java
Jeff Russo
CMPS 374: Software Engineering
Table of Contents:
Abstract..............................1
History...............................1
Intro to Sudoku..................1
Project Overview...............2
Solving Techniques............3
Application of Threads.......4
Problems and Solutions......5
Current Status.....................6
Uses and Future..................7
Works Cited........................9
I will be completing a computerized Sudoku solver for my project with a graphical user
interface using Java Swing. The solver will implement threads using Java's useful concurrency
resources. I am using threads for my project because if used correctly they can solve the puzzle
quicker than a single process. There are many techniques used for solving these puzzles, all
which can run as independent threads, simultaneously. This project will show the advantage of
threading a program that has many parts than can run concurrently. Almost all processors are
now designed to run two or more threads simultaneously and this program will take full
advantage of that. I will create an .exe file using Jsmooth which compiles Java class files into
executable files. If the system that the file is run on does not have a JVM installed, the file will
let the user know and tell him/her to install it.
The history of Sudoku puzzles can be traced back to the Swiss mathematician Leonhard
Euler. He developed Latin Squares which are grids in which a number occurs only once
horizontally and vertically. Sudokus did not become popular or get their name until the 1980's
when a Japanese puzzle maker created the first puzzles and made them popular. Sudoku comes
from the Japanese Su which means number and Doku which means single. The modern Sudoku
was originally made by a puzzle company in Japan. Maki Kaji told his company, Nikoli, to
publish the modern day Sudoku puzzle. It became a hit in newspapers and magazines in Japan.
In the 2000's Wayne Gould, a retired judge from Hong Kong developed a program to generate
puzzles. He convinced The Times, a newspaper from London to put them in their papers. In late
2004, Sudokus were being published in newspapers across the country. They spread very
quickly after that and are now available in many newspapers, magazines, and websites
throughout the world.
Sudoku is a game in which
there is one player who is given the
task of solving a puzzle through
logic. The most popular size puzzle
is a 9x9 grid consisting of nine 3x3
sub squares, nine rows, and nine
columns. A Sudoku can be any size
and can even be a rectangle (2x3
sub squares). For my project I will
focus on 9x9 Sudokus. The picture
to the right depicts a typical Sudoku
puzzle. A player must add the
numbers 1-9 to the puzzle in a way
such that all rows, columns, and sub
squares
have
exactly
one
occurrence of each number. Ex:
One row cannot contain two 7’s.
The plan for my project is to write a program which uses threads in Java to solve Sudoku
puzzles. This will be a very effective and efficient way to solve these puzzles as I can apply
multiple solving techniques at the same time to a given board. Java will make coding the solver
simpler as the language already has many features to deal with all types of data and has extensive
libraries for concurrency. I will make use of many libraries including ArrayLists, semaphores,
and output streams. The BitSet class may be used to represent an array of possible solutions.
This is still in question due to the reliability in multithreaded applications. I will also make use
of the wrapper class for Integers as they have methods to take care of many low level operations.
The program will be shown through a Swing GUI which will make use of action listeners. The
player will be given the option to solve the puzzle him/herself or have my program solve it for
him/her.
The solver will give the player the option to enter a puzzle or to have the program pick a
random one from a database which I plan on creating in my senior year. If the user has chosen to
enter a puzzle, the solver will first display a blank board (9x9 grid). Once the puzzle has been
fully entered, the program will check to make sure it is a legitimate board. After this, the user
can begin solving manually or tell the program to solve it for him/her. Each square will show the
“pencil marks” which is a list of possibilities that the square can possibly be. Throughout the
solving process these are narrowed down to one through my solving techniques. At any time, if
the user gets stuck and cannot finish the puzzle, they will be able to click a “Finish Puzzle For
Me” button which will take the puzzle as it is and solve it completely. The program will prevent
the user from solving a square
incorrectly or removing a
possibility that is the answer.
The GUI will be created
using Java's swing package. I
will make use of Jbuttons,
JtextFields, action commands,
and action listeners. On the
right is a screen shot from an
example puzzle before solving
it.
Each possibility is
represented by a JButton and
the squares that have been
solved are JtextFields. To solve
for a given possibility, the user
right clicks on it. To remove a
possibility from the square the
user left clicks it. This is much simpler than having to type in number individually and can be a
time saver for users who solve Sudokus often. Using this setup also prevents the user from
entering inappropriate data such as letters. To make this readily available to the cs department, I
would like to put this game on my website. I would then be able to show it to anyone interested
in viewing or playing it. To do this, I will use Jsmooth. This is an application that takes Java
class files and compiles them into a working executable file. This also will prompt the use to
install Java if it is not already on the user's machine. I would then put this file on my website for
people to download and play the game or use it to solve puzzles.
There
are
many
solving
techniques used to solve Sudokus. The
simplest is an obvious one. If a square
has only one possibility then that must be
the solution. The next technique is to
look in a row, col, or sub square and look
for a single occurrence of a possibility.
An example would be if there were six
unsolved squares in a row, but only one
of them had the possibility of having a 3,
so 3 must go there. This is true because
every row, col, and sub square must have
exactly one occurrence of the numbers 19. The pointing set or sub square/row or
column interaction technique is a little
more complicated. This is when a
possibility must go in a certain row or
column within a sub square. This creates the ability to eliminate that possibility from all the
other squares in the same row or column. The picture above illustrates this very well. Since a 7
must go in column two of sub square one, 7 can be eliminated from being a possibility from the
remaining squares in column two. These are all of the simple techniques used to solve Sudokus.
The more complex solving techniques begin with subsets combined with the pigeon hole
principle to eliminate possibilities. These subsets are called doubles, triple, and quadruplets.
They occur when the number of possibilities occupying a set of squares equals the number of
squares in the set. On the right is a
hidden subset which is when there are
other possibilities in the squares as
well as the subset numbers. This is a row from a Sudoku where 2, 5, and 7 can only occur in the
three squares where they are highlighted green. This is a triple. It is hidden because 6, 8, and 9
also occur in these three squares. Once the hidden triple is found, all possibilities except 2, 5,
and 7 can be removed from the squares in the triple. Three possibilities occur in three “holes” so
other “pigeons” must go elsewhere. A “naked” or obvious triple is when the three possibilities
are the only three numbers occupying the three squares. You may notice the naked triple 6, 8,
and 9 in the same row as the hidden triple. This is because the number of squares in a naked
subset plus the number of squares in a hidden subset equal the total number of unsolved squares
in a row, col, or sub square. My solver will only be looking for naked subsets as these are much
easier to spot than hidden ones and have the same solving power.
The X-Wing solving technique uses two columns and two rows. If a possibility occurs in
exactly two squares in a two different rows and these squares are also in only two columns then
an X-Wing is present. The possibility can be removed from the two columns in squares other
than the ones used to find the X-Wing. A similar technique called the Swordfish uses three
columns and three rows. If a possibility occurs in exactly two squares in three different rows and
these six squares are also in three columns then a Swordfish has been found. The possibility can
be removed from the three columns in squares other than the ones used to find the Swordfish.
Both of these techniques can be applied to rows and columns interchangeably.
There are even more complex solving techniques that I will try to implement such as
forcing chains, XY-Wing, and XYZ-Wing. These techniques are only needed to solve the most
difficult puzzles so I will work on them after I have a working skeleton for my project. The
puzzles they are used to solve would take a person with pencil and paper a very long time to
solve. I am more concerned with getting a working app together and getting my Swing GUI
working before implementing these complex techniques. Once I have the basics completed and
get a better understanding of threads then implementing these techniques will be easier.
My program will be written in Java using threads. I am using them because parallel
processing is becoming more prominent and when implemented correctly can be much faster
than a regular single process program. This is evident in Intel's newest line of processors. They
are all at least a dual core if not a quad core, with the fastest having six, and are designed to run
at least four processes at a time. The high-end i7 can efficiently run twelve processes
concurrently on six different cores using hyper-threading. My program will be able to solve this
puzzle many times faster than a conventional solver because it can apply many techniques at the
same time. This not only finds solutions faster, but it also eliminates the need to run certain
techniques before running others.
I will implement threads into my program by making each technique a new thread. I am
using the sleep(int ms) command to keep these threads from taking up too many resources by
constantly checking when it is unnecessary. When a thread cannot do work or the work is
unnecessary it will “go to sleep” and free up CPU resources. This will make it possible to have
many different solving threads attacking one problem at once, solving the puzzle quicker.
There will be a main solver thread which initializes all solver threads as well as Square
threads. The solver thread will keep track of the puzzle and will quit when the puzzle is solved
by the program and by the player if there is one playing. It will begin the solving process by
starting up all solver threads. Each Square thread will contain all the info needed for solving the
square itself. It will have an ArrayList containing the possibilities, a reference back to the main
solver thread, the value of the square, the row, and the column. The array of possibilities may be
represented as a BitSet as this uses many less resources and has bit level operations which can
accomplish the same thing as dozens of lines of regular code. The square will check to see if it is
down to one possibility. If it is then it will solve itself, otherwise it will sleep() for a few
hundredths before checking again. When the square is solved, the thread's process is killed to
free up resources for other solvers. The most complex solving techniques will not begin until
needed because they are very expensive and are more of a hindrance than help at the beginning
stages of the solving process. This is one of the places where I will use the sleep() command to
have the thread wait a tenth of a second before beginning.
Using these threads will be much more efficient than using a single process. Many
solvers can attack the same square at once and solve it quicker. This can create minor problems
which I will discuss later, but most have simple solutions. When a thread is complete, it quits,
which frees up more resources for others, which could not happen in a single process program.
A single process would also be forced to do one solving technique at a time, while using threads
will allow my program to use every technique at any given time. As processors become more
focused on parallel processing my program will have even more of an advantage as it will be
able to take full advantage of the processor's capability. A single process program will still be
stuck processing on one core while mine will be split across multiple cores with multiple threads
executing simultaneously.
There are a few obstacles I have foreseen in my project. They are not major issues, but
do need to be taken care of. Although some of these thrown exceptions do not cause the program
to crash or output bad results, the user would not know what to do with them. One thing that I
will always be trying to improve on is performance as well. Methods in my program are
executed hundreds of times while my program runs so every bit of optimization will make a
significant difference and is saving time. I will use counters and flags to prevent solver threads
from unnecessarily trying to solve in a given set of squares when they cannot be solved further
by the technique.
When executing my program it will sometimes throw exceptions for array index out of
bounds in this method:
85
86
87
88
89
90
91
92
/* Removes a possibility from the ArrayList. */
public void remPoss(Integer k) {
/* Known issue: More than one method removing possibility k and the
second remove() returns a -1 as the element k does not exist in Poss */
try{
Poss.remove(k);
}
93
94
catch (Exception e){}
}
It was throwing exceptions because after one solving thread removed a possibility,
another tried to do the same exact thing. This would throw the array index out of bounds: -1
exception because it no longer exists in the ArrayList. I put in the try-catch statement to catch
the exception and comments to make sure anyone looking at this code knows why its there. It
should be noted that this exception had no effect on the correctness of the solver and did not
create a logical problem.
In this next block of code I am using an arrays of counters to optimize my solving process
by preventing unnecessary use of a technique:
31
32
for(Integer Pos=1;Pos<Solver.getSqLength()+1;Pos++){
if(Solver.remaining[Pos]>0){
The first line is a loop that goes through the possibilities 1 to 9. Under the if statement is
many nested for loops and over twenty lines of code. Line 32 checks the possibility's counter to
make sure that there is still a chance of that number be solved for. If all nine 5's were solved for
already, then there is no need to try and find where a 5 goes. This optimization created a visible
improvement in speed by freeing up resources for other solvers to do their job.
Currently my project is a looking like it will be a great success. I do not have everything
I wanted done, but my solver will solve most of “fiendish” puzzles which is the 5th level of
difficulty out of six. The GUI turned out to be more difficult than I expected it, but it is currently
exactly what I had in mind from the beginning. Throughout my research I have tried out a few
other assisted solvers and mine is unique in the way the GUI works and to me is the simplest and
easiest to use. I definitely underestimated the difficulty of using threads. There are many things
that need to be accounted for when using threads that don't need to be when not. The thing is
had the most trouble with was the GUI. When multiple threads are changing it at the same time,
there is an exception thrown that completely crashes the program and solves the puzzle
incorrectly. To stop this from happening, I researched and after looking through Java's API I
found this:
SwingUtilities.invokeLater(
new Runnable(){
public void run(){...}})
This utility makes the block of code a thread and gets added to the scheduler manually.
This makes sure that the code is executing without interruption and will make sure not to affect
the GUI in any bad way. It will check to make sure all GUI elements are where their supposed to
be before executing.
Testing this program was a huge task because of the threads. Errors could not be ignored
ever. The past month of the development I would document every error and make sure I
exhaustively searched my code and logic to make sure it was fixed. In a program with a single
process, errors happen consistently. This is not true with a threaded program. Errors happen at
what can seem random and are not as easily tracked down because the multiple processes are
never interleaved the same twice. Because of this interleaving, each thread must be able to
operate individually and if it can't, appropriate guards must be added. This added protection is
added overhead, and can slow the program down significantly, so code must be written as threadsafe as possible.
I have run into classic concurrency issues such as incrementing and decrementing issues
which I resolved with a semaphore. The most complex issue I had was interruption. One
solving technique is very expensive and takes a long time to run. While this is happening it is
interrupted multiple times and its data set was being changed. This would create an incorrect
result and the program would incorrectly solve a square for the wrong number which would blow
the whole program up. To stop this from happening, all threads that require a static data set
make a copy of the board before each solving iteration. This removes the possibility of the data
set getting destroyed during execution. This brought up new issues that Java had. Because
everything is a reference, I had to go down to the lowest level of detail for every copied object
and make a copy there. Simply assigning the new object the old just pointed to the old one.
Using Java's .clone() method also did not work as it did not actually make a copy.
To assist me in debugging this program I used a file output stream in Java. This was a
pretty simple addition to my program. Every time a solving technique discovers a solution or
makes an elimination, it is printed to a file. This makes it easier for me to see where errors or
bad logic is happening and also can be used to find the difficulty of a puzzle.
For the next semester I would like to add in the final three solving techniques, XY-Wing,
XYZ-Wing, and chains. When these are completed, my solver will be able to complete any
puzzle through logic and will not need to guess. These are quite difficult techniques to
implement so I will work on them last. I would also like to add an option for the user to enter
their own puzzle. This is a simple task, but could cause big problems. How can I decide
whether it is a legitimate puzzle or not? I would also like to make a database of puzzles so the
user can have the option to pick a random puzzle to solve. A few thousand puzzles would be
enough for this project and I think this would not be too difficult a task. There are excel
spreadsheets that contain this volume of puzzles available on the internet. Given the time I may
even make a random puzzle generator which makes a new puzzle every time the user wants a
new puzzle. This would be a much more portable option to having to keep a database with my
executable file.
This solver can be used by Sudoku enthusiasts as an easy method to check their solutions
or to practice using the more difficult techniques. The assisted solving GUI will make this
simple and fun. When this application gets on the web it will be easy to access and use. I think
the most important and valuable part of this project is the fact that it is executed using threads.
The newest improvement in processing is parallel computing and this program will make good
use of it. It is a good example to build a more powerful program off of. I know this will be a
great learning experience for myself and will also help anyone looking to learn about threads and
parallel processing. A simpler version of my program designed to solve only the simplest of
puzzles would be a great teaching tool for using threads similar to the Coloring Contest created
by Dr. Beidler. I think this would be an excellent undergrad project to show to possible
employers as it combines many things I have learned throughout my education at the University
of Scranton.
Works Cited
http://www.sudokudaily.net/history.php
http://www.sudopedia.org/wiki/Solving_technique
http://www.sadmansoftware.com/sudoku/solvingtechniques.htm
http://www.intel.com/products/processor/corei7/index.htm
© Copyright 2026 Paperzz