Skip to end of metadata
Go to start of metadata

Introduction:

The main data structure for this week's project was stack and 2D array.  Similar with last week's Game of Life, 2D array of the Cell was used to visualize the board for Sudoku.  Stack was used to store possibe valid values for each location of grid.  If a value was valid, it was pushed, i.e. added, to the stack.  If not, the value was popped, i.e. removed.  Once I updated Cell and Board class and created Sudoku class, I used LandscapeDisplay class as GUI for Sudoku game.  Cell class contains information about each cell of grid, such as row/column index, value, and whether it is locked.  Board class constructs 2D array of cells and contains a number of useful methods that can be used to obtain or evaluate information about each cell.  Sudoku class initializes the board and constructs solve method that uses stack to find possibe valid values.  LandscapeDisplay class builds GUI, but it is initialized in Sudoku class.  Thus, run Sudoku class to test the game.

Main Code:

Board Class)

For read method, I used a while loop to loop through each line in a text file.  If there is character, or value in the line, it will be added to each location of 2D array of Cells.

In order to read in the text file, I used try/catch statement.

For validValue method, I used three for loops to check if the value was unique in its row, column, and the local 3x3 square.

Sudoku Class)

Sudoku class has two constructors.  The default constructor builds a board of all-zero values.  The second constructor build a board of n number of randomly generated initial values.

I used while loop to generate a certain number of random row/column index and values and then added them to the board if they were valid.

LandscapeDisplay Class)

In order to use GUI to display Sudoku, I needed to add draw methods to Cell and Board class.  As instruction recommended, I used drawChars() method draw a value of each cell.  

To do so, I needed to convert the value of cell to character first through type casting and then saved it to an arry.

Once I added draw method Board class, which essentially loops through each cell and calls Cell class's draw method, and initialized the LandscapeDisplay fields in Sudoku class's constructors, I was able to display Sudoku through GUI.

Figure 1 is initial board and figure 2 is the final board (solved).

 (figure 1).   (figure 2).

Note that the labels and buttons are my extensions, which will be explained below.

Explorations:

1) I used simulation button (automation extension) to observe how many of each case have a solution.  After running 5 boards of 10, 20, 30, 40 ,50 initial values, I found out that starting with number 30, my Sudoku class's solve method started to fail.

2) Similarily, I ran simulation of different initial values five times.  Below are the results, i.e. average steps, of each starting numbers.

10: 20676

20: 61444

30: 8033

40: 25

50: 11

As the number of intial values increased, the number of steps increaed and then decreased drastically probably because the solve method becomes no longer able to find possible values and fails (note that simulation results will vary because they are located in different cells every time).

Extensions:

  • Make the visualization fancier. Add a button to reset the board and do a new solve. Add output statistics, titles, better coloring, etc.

As figure 1 & 2 show, I changed the color of cells differently based on whether they are on even/odd column of the grid and set the background color to drark grey.  More importantly, I added three buttons and two labels to make my Sudoku class more interactive.  First of all, reset button resets the board of Sudoku.  It can be used after solve/simulation button has been clicked.  

For reset Button, I added reset method to Board and Sudoku class.  Board class's reset method simply returns the grid to its default state, i.e. all-zero values of cells.

Sudoku class's reset method first calls Board class's reset method.  Then it repeats what the second constructor of Sudoku class does: loop through certain number of times to randomly generate initial values for the board.

I set time to zero so that the average steps will be accurate after simulation of 10, 100 or more games.  Another thing to note regarding reset method is that I added a static variable i to Sudoku class so that reset method can remember how many times to generate the random initial values.  I initialize i to the command line argument in the main method so that once Sudoku class is initialized, the number can be saved.

For solve button, I needed to call Sudoku class's solve method in LandscapeDisplay class.  In order to avoid initializing Sudoku class in LandscapeDisplay class, which would not have worked anyway, I declared Sudoku field, called game, in LandscapeDisplay class.  In LandscapeDisplay constructor, I initialized game to be null.  Then, I added setGame(Sudoku game) method to LandscapeDisplay class, which will be used in Sudoku class.

In Sudoku constructor, I called setGame method, which would then enable LandscapeDisplay class to call Sudoku class's methods.

Professor Layton helped me to approach calling solve method problem this way.

 

  • Automate the process of exploring the trends in the simulation. An automated process should be able to analyze the results of hundreds or even thousands of games.

In order to simulate a number of Sudoku games, I created automate method to Sudoku class which takes in a parameter n.  I used for loop to play a n number of games.

In addition to automate method, I created getTime() method in Sudoku class to obtain the steps taken for each game.  

For a similar reason in reset method, I set time back to zero once obtained so that average will be accurate after a number of simulations.

Automation can be used through simulation button in LandscapeDisplay class, which calls automate method and shows the result from automate through average JLabel.

When simulation button is clicked, a pop-up will show asking for user input.  The input determines the number of simulations to run.  The number of populated initial values are determined by command line argument in terminal.

Steps taken is TBD because it only refects a step for one game.  Thus, average steps only will be updated after simulation button is clicked.  Another thing to note is that my Sudoku display will not be updated after simulation, unlike after clicking solve button.

 

  • A small extension is to enable your read method to handle the files with extra spaces.

For this extension, I simply added one conditional statement in Board class's read method.

The logic is that if the line, which is a string array, has no character and therefore empty, the while loop skips that line.  Thus, my read method can handle files with extra spaces.  Below is the snapshot of my terminal after reading Board 20 solved.

Conclusion:

I became more familiar with 2D array and stack through this project and learned how they can be used together to create projects like Sudoku.  However, I still feel a little uncomfortable using stack and would like to know its capabilities more.

For this project, I received help from Professor Layton and used Selim's report as a point of reference. 

Labels