home *** CD-ROM | disk | FTP | other *** search
- unit TicTac;
- {
- TICTAC.PAS unit for implement abstract data types MOVE,
- LOCATION, GAME
- author bruce f. webster
- last update 12 dec 87
- }
- interface
-
- { definitions for abstract data type Move }
-
- type
- Move = (BLANK,X,O);
-
- function Opposite(M : Move) : Move;
-
- { definitions for abstract data type Location }
-
- const
- GLim = 9;
-
- type
- Location = 1..GLim;
-
- { defintions for abstract data type Game }
-
- type
- Board = array[Location] of Move;
- Game = record
- Grid : Board;
- Next,Win : Move;
- Moves : Integer
- end;
-
- function GetLoc(var G : Game; L : Location) : Move;
- function NextMove(G : Game) : Move;
- function MovesMade(G : Game) : Integer;
- function GameOver(var G : Game) : Boolean;
- function Winner(G : Game) : Move;
- procedure DoMove(var G : Game; L : Location);
- procedure NewGame(var G : Game; First : Move);
-
- implementation
-
- function Opposite(M : Move) : Move;
- {
- purpose return opposite of value passed
- pre m has a value of X, O, or BLANK
- post if m = X, then returns O
- if m = O, then returns X
- else returns BLANK
- }
- begin
- case M of
- BLANK : Opposite := BLANK;
- X : Opposite := O;
- O : Opposite := X
- end
- end; { of proc Opposite }
-
- procedure SetLoc(var G : Game; L : Location; M : Move);
- {
- purpose sets a location in the game to a given value
- pre l is in the range 1..9
- m has a value of X, O, or BLANK
- post location l in the game has value m
- }
- begin
- G.Grid[L] := M
- end; { of proc SetLoc }
-
- function GetLoc(var G : Game; L : Location) : Move;
- {
- purpose returns value of a given location in the game
- pre g has been initialized, l is in the range 1..9
- post returns value of g at location l
- }
- begin
- GetLoc := G.Grid[L]
- end; { of proc GetLoc }
-
- function NextMove(G : Game) : Move;
- {
- purpose returns next move
- pre g has been initialized
- post if game is not over
- then returns X or O
- else returns BLANK
- }
- begin
- NextMove := G.Next
- end; { of func NextMove }
-
- function MovesMade(G : Game) : Integer;
- {
- purpose returns number of moves made in game so far
- pre g has been initialized
- post returns a value in the range 0..9
- }
- begin
- MovesMade := G.Moves
- end; { of func MovesMade }
-
- procedure InARow(var G : Game; I,J,K : Location);
- {
- puporse checks for three X's or O's in a row
- pre g has been initialized, 0 or more moves made
- post if locations i,j,k all have the same value
- and that value is not BLANK
- then the winner is set to that value
- }
- begin
- with G do begin
- if Win = BLANK then begin
- if (Grid[I] = Grid[J]) and (Grid[J] = Grid[K])
- and (Grid[I] <> BLANK) then Win := Grid[I]
- end
- end
- end; { of proc InARow }
-
- procedure CheckForWin(var G : Game; L : Location);
- {
- purpose see if last move won the game
- pre g has been initialized, 1 or more moves made,
- l is in the range 1..9, location l has X or O,
- last move was made at location l
- post if l forms 3 X's or O's in a row
- then the winner is set to that value (X or O)
- }
- begin
- case L of
- 1 : begin
- InARow(G,1,2,3);
- InARow(G,1,5,9);
- InARow(G,1,4,7)
- end;
- 2 : begin
- InARow(G,1,2,3);
- InARow(G,2,5,8)
- end;
- 3 : begin
- InARow(G,1,2,3);
- InARow(G,3,5,7);
- InARow(G,3,6,9)
- end;
- 4 : begin
- InARow(G,1,4,7);
- InARow(G,4,5,6)
- end;
- 5 : begin
- InARow(G,1,5,9);
- InARow(G,2,5,8);
- InARow(G,3,5,7);
- InARow(G,4,5,6)
- end;
- 6 : begin
- InARow(G,3,6,9);
- InARow(G,4,5,6)
- end;
- 7 : begin
- InARow(G,1,4,7);
- InARow(G,3,5,7);
- InARow(G,7,8,9)
- end;
- 8 : begin
- InARow(G,2,5,8);
- InARow(G,7,8,9)
- end;
- 9 : begin
- InARow(G,1,5,9);
- InARow(G,3,6,9);
- InARow(G,7,8,9)
- end
- end
- end; { of proc CheckForWin }
-
- function GameOver(var G : Game) : Boolean;
- {
- purpose returns status of game (over or not)
- pre g has been initialized, 0 or more moves have been made
- post if game is over
- then returns TRUE
- else returns FALSE
- }
- begin
- GameOver := (G.Win <> BLANK) or (G.Moves = GLim)
- end; { of func GameOver }
-
- function Winner(G : Game) : Move;
- {
- purpose returns winner of game
- pre g has been initialized, the game is over
- post if there are 3 X's in a row, returns X
- if there are 3 O's in a row, returns O
- else returns BLANK (draw)
- }
- begin
- Winner := G.Win
- end; { of func Winner }
-
- procedure DoMove(var G : Game; L : Location);
- {
- purpose make next move in game
- pre g has been initialized, 0 or more moves made,
- the game is not over, l is in the range 1..9,
- getloc(g,l) is BLANK
- post the next move is made at location l
- a possible win is checked
- if game is not over,
- then the next move is toggled
- else the next move is set to BLANK
- }
- begin
- with G do begin
- SetLoc(G,L,G.Next);
- Moves := Moves + 1;
- CheckForWin(G,L);
- if not GameOver(G)
- then Next := Opposite(Next)
- else Next := BLANK
- end
- end; { of proc DoMove }
-
- procedure NewGame(var G : Game; First : Move);
- {
- purpose initialize a new game
- pre first has a value of X or O
- post g has been initialized:
- locations 1..9 are setBto BLANK
- the next move is set to first
- the winner is set to BLANK
- the number of moves is set to 0
- }
- var
- I : Integer;
- begin
- with G do begin
- for I := 1 to GLim do
- SetLoc(G,I,BLANK);
- Next := First;
- Win := BLANK;
- Moves := 0
- end
- end; { of proc NewGame }
-
- end. { of unit TicTac }