16.3Rendering the Sudoku Grid
What we need to do is to render a table that looks like a Sudoku grid. We start by defining a method that creates a table and uses style tags for formatting.
WebSudoku>>renderHeaderFor: aString on: html
html tableData
class: 'sudokuHeader';
class: 'sudokuHBorder';
class: 'sudokuVBorder';
with: aString
WebSudoku>>renderContentOn: html
self renderHeaderFor: 'This is a test' on: html
Make sure that you invoked the class side initialize
method and then run the application by visiting http://localhost:8080/sudoku. Your browser should display the string This is a test.
We need two helper methods when creating the labels for the x
and y
axis of our Sudoku grid. You don’t need to actually add these helper methods yourself, they were already loaded when you loaded the Sudoku package:
Integer>>asSudokuCol
"Label for columns"
^ ($1 to: $9) at: self
Integer>>asSudokuRow
"Label for rows"
^ ($A to: $I) at: self
First we print a space to get our labels aligned and then draw the label for each column.
WebSudoku>>renderBoardOn: html
html table: [
html tableRow: [
self renderHeaderFor: '' on: html.
1 to: 9 do: [ :col |
self renderHeaderFor: col asSudokuCol on: html ] ] ]
We make sure that the method WebSudoku>>renderContentOn:
invokes the board rendering method we just defined.
WebSudoku>>renderContentOn: html
self renderBoardOn: html
If you run the application again, you should see the column labels as shown in Figure 109.
We now draw each row with its label, identifying the cells with the product of its row and column number.
WebSudoku>>renderBoardOn: html
html table: [
html tableRow: [
self renderHeaderFor: '' on: html.
1 to: 9 do: [ :col | self renderHeaderFor: col asString on: html ] ].
1 to: 9 do: [ :row |
html tableRow: [
self renderHeaderFor: row asSudokuRow on: html.
1 to: 9 do: [ :col |
html tableData: col * row asString ] ] ] ]
If you have entered everything correctly, your page should now look like Figure 110.
Now we define the method renderCellAtRow:col:on:
that sets the style tags and redefine the renderContentOn:
as follows so that it uses our style sheet.
WebSudoku>>renderContentOn: html
html div
id: 'sudokuBoard';
with: [ self renderBoardOn: html ]
WebSudoku>>renderCellAtRow: rowInteger col: colInteger on: html
html tableData
class: 'sudokuHBorder' if: rowInteger \\ 3 == 0;
class: 'sudokuVBorder' if: colInteger \\ 3 == 0
You also need to change WebSudoku>>renderBoardOn:
so that it uses our new method WebSudoku>>renderCellAtRow:col:on:
.
WebSudoku>>renderBoardOn: html
html table: [
html tableRow: [
self renderHeaderFor: '' on: html.
1 to: 9 do: [ :col | self renderHeaderFor: col asString on: html ] ].
1 to: 9 do: [ :row |
html tableRow: [
self renderHeaderFor: row asSudokuRow on: html.
1 to: 9 do: [ :col | self renderCellAtRow: row col: col on: html ] ] ] ]
If you refresh your page again, you should finally see a styled Sudoku grid as show in Figure 111.
Next we will use a small helper method asCompactString
that given a collection returns a string containing all the elements printed one after the other without spaces. Again, you do not need to type this method, it was loaded with the ML-Sudoku code.
Collection>>asCompactString
| stream |
stream := WriteStream on: String new.
self do: [ :each | ws nextPutAll: each printString ].
^ stream contents
We define a new method renderCellContentAtRow:col:on:
that uses asCompactString
to display the contents of a cell. Each cell displays its possibility set. These are the values that may legally appear in that cell.
WebSudoku>>renderCellContentAtRow: rowInteger col: colInteger on: html
| currentCell possibilites |
currentCell := MLCell row: rowInteger col: colInteger.
possibilites := sudoku possibilitiesAt: currentCell.
possibilites numberOfPossibilities = 1
ifTrue: [ html text: possibilites asCompactString ]
ifFalse: [
html span
class: 'sudokuPossibilities';
with: possibilites asCompactString ]
We make sure that the renderCellAtRow:col:on:
invokes the method rendering cell contents.
WebSudoku>>renderCellAtRow: rowInteger col: colInteger on: html
html tableData
class: 'sudokuHBorder' if: rowInteger \\ 3 = 0;
class: 'sudokuVBorder' if: colInteger \\ 3 = 0;
with: [ self renderCellContentAtRow: rowInteger col: colInteger on: html ]
Refresh your application again, and your grid should appear as in Figure 112.