Tutorial - Project - Tic-Tac-Toe 2

We are now going to upgrade the Tick Tac Toe program using some of the new features we have learned. Specifically reading in an array or records, the use of arrays and the use of shape routines.

If you want to try this yourself first then go ahead. Otherwise look at my version which is here. I will go through it in detail.

The first section is just setting up the layout parameters to fit the board to the display size.

The first line of interest is :-

Type TPlayer = ( Player_Nought = "O", Player_Cross = "X" );

This defines an enumerated type for the two players. The "Player_Nought" is the internal name that can be ( but isn't ) used within the program. This name can also be used in data files. The value in quotes is a string that can only be ( and is ) used within the data files.

Next is a structure to hold an individual record read from the data file.

Type MoveRecord = { TPlayer piece, Number row, Number col };

Here the piece is held as an enumerate type. This will help with the type-checking of the code by the system.

Next a Shape type.

Type TPlayerSymbol = Shape(Number size);

This is an example of a routine type. Any variable of this type can hold a reference to a shape routine that takes a single Number parameters - which is just what the player symbol routines are.

This is where it starts getting clever.

Type TDispatchTable = TPlayerSymbol[TPlayer];

This defines an array type. The index of the array is the enumerate type of the player. The element type is one of the routine variables. So you can have an array of routines indexed by the player.

We can create an instance of this table type and initialise it to hold the drawing routines for each of the players.

Const TDispatchTable Dispatcher = [Nought, Cross];

Nought and Cross are the Shape routines defined later. There are two element in the enumerated type so there are exactly two elements in the list used to initialise the array.

Finally we define an array type to hold an array of moves.

Type MoveArray = MoveRecord[];

This is left as an open array so that it can hold as many moves as required.

Now we get onto the code. The first line reads in the data :-

movelist := ReadData("TUTSAMPLES:/tictactoe.txt");

As the data file only contains simple data fields there is no need for a format file to be specified. If there is any problem at runtime an error will be generated and, as we are not trapping it, the program will terminate.

The data array is passed to the main drawing routine.

Game(movelist) => { HBorder, VBorder };

The entire drawing code has been encapsulated in a single routine so that the location can be specified just one.

The main game drawing routine is defined as a Shape because it writes to the canvas.

Shape Game(Const Ref MoveArray movelist)

The array is passed as a constant reference. The use of Ref means that the system does not have to make a copy. The use of Const means the caller does not have to worry about the data begin changed and also make it more flexible ( e.g. you can use a literal array for testing ).

We start by drawing the grid.


The whole drawing uses the same origin, the top right corner, so there is no need to specify where to draw the grid.

We can use an 'Over' loop to process the data array.

Over movelist As move Do

The 'movelist' is a Const so the 'move' itself will act as a Const, but as we will never try to modify a record this is what we want.

Now we get to the really interesting line :-

Dispatcher[move.piece](TokenSize) => CellCentre(move.row, move.col);

The Dispatcher array is the list of Shape routines; this is indexed by the player enum. The piece field within the move record is just such an enum. So this value is used to index the array and this will yield the appropriate Shape. This shape is called with TokenSize as a parameter.

The graphics context consist of a call to calculate the position of the piece based on the row and column in the record.

The rest essentially consists of routines you have already seen.

tictactoe_3A.grs tictactoe.txt Output of tictactoe_3A.grs tictactoe_3A.png