It is ugly, snowy and rainy day overhere in Sweden. What you do such a day? I have been lazy and done some more Java programming to kill my time.
First thing was to update my Textfield to become a SudokuField. Obviously to become a Sudoku input, a text field has to follow few rules: it has to allow only certain characters to be typed in and only certain number of them. It also has to obey rules of Sudoku game, which means no duplicates in rows, columns or mini grids.
Range and number of characters depends obviously on type of Sudoku game, like range for 9×9 Sudoku would be digits 1 to 9, and for 16×16 would be numbers 1 to 16. Sudoku rules are of course same for all types (no duplicates allowed). First two checks can be implemented locally in a text field. Text fields have DocumentFilter class of JText components which is supposed to be used for exactly this purpose: validating the input. Its two methods: insertString and replace are places to check for range and number of characters in input.
Checking if input is valid according to game rules is little bit more difficult. A single SudokuField is tiny isolated island that only knows of its own input. It needs somehow to become aware of its fellow siblings in same row, column and mini grid. Since all inputs are children of SudokuPanel instance, I think it is a good place to have a method there that can check for validity of move. I call it isValidMove(String s, int r, int c,int g).
For the concept, there is nothing more involved here than an array of sizexsize JTextField objects, where size is typically 9, but can be 16, 25 or some other size. JPanel can be used both in web applets or JFrame for desktop applications and is a container of my choice here.
References to fields are held in three arrays: rows, cols and grds. Having three sets of references will simplify some traversals later on.
There are some issues to deal with drawing of the board. Text fields are Swing components and as such have some default borders. They look quite OK with those borders; but I have found the panel looks a bit better without them, so I have removed them. Furthermore I use GridLayout to evenly space text fields on the panel. By leaving vertical and horizontal gaps between fields, divider lines are “drawn” for free. Finally divider lines for mini grids, that usually are drawn in some other colour, are drawn on a separate panel on top of SudokuPanel; think GlassPane. I used GlassPane because the divider lines were sometimes overwritten by text fields when text was updated. Painting on top of entire panel solves the problem.
It turned to get around 200 lines of code for those 3 classes, but it is OK foundation to write the rest of Sudoku application on. It is also quite general, but there are few places tied to a 9×9 type; mostly document filter class, which is hardcoded to accept only characters 1 – 9. Obviously I have to abstract the alphabet that is allowed in a game, but for the moment it will have to rest in favor for some other functionality.
One generality is that strings from text fields are never converted to numbers. I see no reason to do that. Sure it is faster to compare numbers than Java Strings, but imagine a Sudoku of 16×16 sizes where allowed characters are numbers in hexadecimal system. Sudoku is really about symbols not numbers. It happened that symbols for numbers 1 – 9 are mostly used, but it could be colors, letters or any other symbols that have to be placed on the board according to Sudoku rules.
Some really annoying stuff that took quite a scratching to figure out was due to different versions of Java plugin installed. It seems that JRE 1.7 works fine in IE9, but Firefox and Chromium use older, 1.6. I didn’t found a way to get either of those browsers to accept latest 1.7 JRE, so I had to fix panel class and add some padding to get it to display nicely in older versions. Seems like there was a bug in older version of GridLayout manager as I googled for some possible problems, but I am not sure. From the picture it is possible to see that in older version (Chromium, Firefox), text fields are rendered from point (0,0), while newer respects horisontal and vertical gap from all four borders.
Code to fix it:
String jv = System.getProperty("java.version");
version = Integer.parseInt(jv.charAt(2)+"");
if(version < 7)
// do something here if desirable ...
Finally my little Sudoku framework as an applet:
Java applet that draws a Sudoku frame.
When using applet you can click on fields and input numbers 1 - 9. The applet will prevent incorrect input and beep. Obs, you can't play sudoku! It is just a gui with no brains yet
Latest Firefox has some issues with rendering; the applet is not rendering properly if page is scrolled! It renders first time, but when page is scrolled it gets messed up and is not redrawn properly.