| home
| contents
| previous
| next page
| send comment
| send link
| add bookmark |
ttt.t
tic-tac-toe
%
% A simple game of tic-tac-toe adapted from Dr. Dobb's Journal,
% December 1994, p.132
%
% ---- board markers ----
const PLAYER : char := 'X'
const COMPUTER : char := 'O'
const FREE : char := ' '
% --- game position on screen ---
const LEFT : int := 18
const TOP : int := 5
% --- game board ---
var board : string := " "
% --- winning combinations ---
var wins : array( 8, 3 ) of int
program
var mv, mv_c, mv_p, moves : int
init_wins
loop
cursor( 0 )
displayboard
% --- get player's first move ---
mv := getmove
exit when mv = 0
% --- set computer's first move ---
if mv ~= 5 then
setpiece( 15, 5, COMPUTER ) % center if available
else
setpiece( 15, 1, COMPUTER ) % upper left otherwise
end if
moves := 2
loop
exit when moves >= 9
mv := getmove % player's next move
moves := moves + 1
watch( board )
if won then
message( 1, "You win" )
exit
end if
if moves = 9 then
message( 1, "Tie" )
else % find computer's next move
mv_c := canwin( COMPUTER )
mv_p := canwin( PLAYER )
if mv_c ~= 0 then % win if possible
setpiece( 15, mv_c, COMPUTER )
elsif mv_p ~= 0 then % block player's win potential
setpiece( 15, mv_p, COMPUTER )
else
nextmove
end if
if won then
message( 1, "I win" )
exit
end if
moves := moves + 1
end if
end loop
cursor( 1 )
put ""
put "Play again? (y/n) "...
exit when getkey = ord( 'n' )
board := " "
end loop
scroll( 0, 24, 0, 79, 7, 0, 0 )
end program
%
% initialize wins array
%
procedure init_wins
% --- winning rows ---
wins( 0, 0 ) := 1
wins( 0, 1 ) := 2
wins( 0, 2 ) := 3
wins( 1, 0 ) := 4
wins( 1, 1 ) := 5
wins( 1, 2 ) := 6
wins( 2, 0 ) := 7
wins( 2, 1 ) := 8
wins( 2, 2 ) := 9
% --- winning columns ---
wins( 3, 0 ) := 1
wins( 3, 1 ) := 4
wins( 3, 2 ) := 7
wins( 4, 0 ) := 2
wins( 4, 1 ) := 5
wins( 4, 2 ) := 8
wins( 5, 0 ) := 3
wins( 5, 1 ) := 6
wins( 5, 2 ) := 9
% --- winning diagonals ---
wins( 6, 0 ) := 1
wins( 6, 1 ) := 5
wins( 6, 2 ) := 9
wins( 7, 0 ) := 3
wins( 7, 1 ) := 5
wins( 7, 2 ) := 7
end init_wins
%
% find next available open space
%
procedure nextmove
label nextmove_exit :
var i : int
var j : int
for i := 0 ... 8 do
if board( i ) = FREE then % try for win
j := i % save last free space
board( i ) := COMPUTER % trial
if canwin( COMPUTER ) > 0 then
setpiece( 15, i + 1, COMPUTER )
goto nextmove_exit
end if
board( i ) := FREE
end if
end for
setpiece( 15, j + 1, COMPUTER )
nextmove_exit :
end nextmove
%
% get the player's next move and display it
%
function getmove : int
var mv : int := 0
loop
exit when mv ~= 0
message( 0, "Move (1-9)?" )
mv := getkey
mv := mv - ord( '0' )
if mv < 1 or mv > 9 then
message( 1, "invalid, re-enter" )
mv := 0
elsif board( mv - 1 ) ~= FREE then
message( 1, "invalid, re-enter" )
mv := 0
end if
end loop
message( 1, " " ) % clear error message
setpiece( 15, mv, PLAYER )
return mv
end getmove
%
% test to see if the game has been won
%
function won : boolean
var i, pl0, pl1, pl2 : int
var r : boolean
for i := 0 ... 7 do
pl0 := wins( i, 0 ) - 1
pl1 := wins( i, 1 ) - 1
pl2 := wins( i, 2 ) - 1
if board( pl0 ) ~= FREE then
if board( pl0 ) = board( pl1 ) and
board( pl0 ) = board( pl2 ) then
r := true
exit
else
r := false
end if
end if
end for
return r
end won
%
% test to see if a player (n) can win this time
% return 0 or winning position
%
function canwin( n : char ) : int
var i, w : int
for i := 0 ... 7 do
w := trywin( n, i )
if w ~= 0 then
return w
end if
end for
return 0
end canwin
%
% test a row, column, or diagonal for a win
% return 0 or winning board position
%
function trywin( n : char, wn : int ) : int
var nct, zct : int := 0
var i, pl : int
for i := 0 ... 2 do
pl := wins( wn, i ) - 1
if board( pl ) = FREE then
zct := i + 1
elsif board( pl ) = n then
nct := nct + 1
end if
end for
if nct = 2 and zct > 0 then
return wins( wn, zct-1 )
end if
return 0
end trywin
%
% display the tic-tac-toe board
%
procedure displayboard
var ln0 : string := "---|---|---"
var ln1 : string := " 1 | 2 | 3 "
var ln2 : string := " 4 | 5 | 6 "
var ln3 : string := " 7 | 8 | 9 "
scroll( 0, 24, 0, 79, 7, 0, 0 )
locate( TOP + 0, LEFT )
putstr( ln1, 7, 0 )
locate( TOP + 1, LEFT )
putstr( ln0, 7, 0 )
locate( TOP + 2, LEFT )
putstr( ln2, 7, 0 )
locate( TOP + 3, LEFT )
putstr( ln0, 7, 0 )
locate( TOP + 4, LEFT )
putstr( ln3, 7, 0 )
end displayboard
%
% set a players mark (O or X) on the board
%
procedure setpiece( color, pos : int, mark : char )
var col, row : int
pos := pos - 1
board( pos ) := mark
col := pos div 3
row := pos mod 3
locate( TOP + col*2, LEFT + row*4 + 1 )
putch( mark, color, 0 )
end setpiece
%
% message to opponent
%
procedure message( y : int, msg : string )
locate( TOP + 8 + y, LEFT )
putstr( msg, 7, 0 )
end message
| home
| contents
| previous
| next page
| send comment
| send link
| add bookmark |
Copyright © 2004, Stephen R. Schmitt