Originally posted 23 September 2012, due at 11:59 p.m. EDT on
6 October 2012, by placing a .java file in a subdirectoty of your cs187 directory on
your edlab account, called
For more information on accessing the edlab, see
here or ask in discussion
(Deadline extended on 5 October 2012.)
Goals of this project:
Questions and answers about this project are collected here.
Note in green added 28 September 2012.
Note in purple added 28 September 2012.
Notes in brown added 29 September 2012.
A Latin square of order 9 is a 9 by 9 array of integers, each in the range from 1 through 9, that never has the same number occurring twice in a row or twice in a column. A sudoku is a Latin square of order 9 that also has the property that if we view the 81 cells as divided into 9 boxes, each a 3 by 3 subsquare, no number occurs twice in the same box.
A sudoku puzzle is a 9 by 9 array of integers in the range from 0 through 9, where a 0 represents a cell that must be filled in. The goal of the puzzle is to replace all the 0's with numbers in the range from 1 through 9 to form a sudoku. In commercial puzzles, care has been taken that there is exactly one sudoku that can be made by replacing the 0's. In general there might be none, or more than one. Your program will either return the first sudoku in lexicographic order, or report that there is no solution.
There are many ways to go about this problem, and we are specifying one which is quite different from the way humans solve such puzzles, but which your computer can execute very quickly. This is a backtrack search -- you will first try to find a number that can go in the first open cell without violating the sudoku property, then a number that can go in the second open cell, and so on. (The order on the cells is left to right in the top row, then left to right in the second row, and so on to the last row.) When you find that no number will go in a particular cell, you backtrack to the previous cell and try the next number there. If you run out of numbers in the first cell, there is no solutions. If you find a complete solution, you stop and report it.
Your input may come from the console as in the sample program on page 182-3 of DJW. The user will enter nine lines of text, each containing nine digits and representing a row of the puzzle. For example, the "difficult" puzzle on the New York Times website for 23 September 2012 (but see below) has the following nine rows:
400520103 090800500 100000000 800430000 000000900 056000700 000600000 030007002 020000405
Note: It is somewhat simpler to read a Board
from a text file if there are spaces between the digits, becasue you can use
nextInt method in the
Scanner class. So if we
were to give you the puzzle above as a text file, it would look like this:
4 0 0 5 2 0 1 0 3
0 9 0 8 0 0 5 0 0
1 0 0 0 0 0 0 0 0
8 0 0 4 3 0 0 0 0
0 0 0 0 0 0 9 0 0
0 5 6 0 0 0 7 0 0
0 0 0 6 0 0 0 0 0
0 3 0 0 0 7 0 0 2
0 2 0 0 0 0 4 0 5
I miscopied the Times sudoku puzzle originally, putting two 7's in the same column. I don't know if the fixed version above is exactly what the Times had, but it does have at least one solution.
We will outline your program for you and define your two most important classes:
Boardobject is a 9 by 9 array of cells, each containing an
intin the range from 0 through nine, and a 9 by 9 array of booleans telling which cells are "fixed". (These are the cells that had positive numbers in them at the start -- these numbers may not be changed.) The
Boardclass should have a method
boolean isBad( ), which tells whether the current position has a positive number occurring twice in any row, column, or box. It should have a method
void move(Move m)that takes a
Moveobject (defined below) and changes its entry accordingly. It should throw a
BadMoveExceptionif the move attempts to change a fixed cell. You may want to define additional getters and setters.
Board class should have a constructor that takes
one parameter of type
String [ ]. This parameter
should be an array of nine strings, each one representing a row of
the puzzle. These strings should have spaces between the digits, as
in the second example above.
Moveobject represents an order to change one cell of a
Board. It has three
intinstance fields, the row and column to be changed and the new value. It has a constructor taking all three of these values and making a new
Moveobject with them. You may want to define additional getters and setters.
SudokuSolverclass where the actual solution of the puzzle will take place. A
SudokuSolverobject will have a
solvemethod that takes one parameter of type
Boardand returns a
String. (Since any
SudokuSolverobject is basically the same, you need just one constructor with no parameters.)
The output string from
solve will be either
exactly the string "This puzzle has no solution." or nine
of text describing the (first) completed solution. That is, there
will be nine lines, separated by "\n" characters, and each line will
have exactly nine digits with exactly one space between each pair of
SudokuSolverobject, create one or more
Boardobjects, run the
solvemethod on each of the
Boardobjects, and compare the resulting strings with the correct answers. We'll make one such driver available -- we may use different example puzzles in the actual grading.
Moveobjects, which you may implement with either a
java.util, or with an
LinkedStack<Move>object from DJW's code base. Note that the names and definitions of the basic stack operations are different in these two cases.
The fundamental idea is to use the stack to record the moves that you are still considering. When you rule out a move, you pop it from the stack and undo it by setting the value of the cell it refers to 0. Then you can replace it with the move to set the same cell to the next value. If you come up with a set of moves that fills all the unfixed cells without causing a conflict, that is your solution. If you exhaust all the possibilities for the value of your first cell, there is no solution.
You should put your classes in your EdLab space, in a directory called "cs187/proj2", and test the behavior with a main method or a driver class. (We will test the code with our own driver class.)
If you create your code within Eclipse (which we encourage but don't require), you will want to ignore the warning message that says "The use of the default package is discouraged". Bear in mind that if you make the mistake of declaring the StringBag class in a package, our driver class will not see it (since it will not be in a package) and we won't be able to test your code.
Last modified 5 October 2012