program tictactoe;
uses ptccrt,windows;
const
computer = 2;
Human = 1;
GoodInput : set of char = ['1','2','3','4','5','6','7','8','9'];
type
playingBoard = array[0..2,0..2] of byte;
ScreenCoord= record
row,column:integer;
end;
var
Screen :array[0..2,0..2] of screencoord;
game,score:playingboard;
ch:char;
WonGame,
gameover:boolean;
Hwin,Cwin,Tie:integer;
EndingResponse:char;
ac:integer;
goesfirst:boolean;
Procedure InitScreen;
var
j:integer;
begin
textcolor(14);
screen[0,0].row := 4; Screen[0,0].column := 12;
screen[0,1].row := 4; Screen[0,1].column := 24;
screen[0,2].row := 4; screen[0,2].column := 36;
screen[1,0].row:= 13; screen[1,0].column := 12;
screen[1,1].row:=13; screen[1,1].column := 24;
screen[1,2].row := 13; screen[1,2].column := 36;
screen[2,0].row := 22;screen[2,0].column := 12;
screen[2,1].row := 22;screen[2,1].column := 24;
screen[2,2].row := 22;screen[2,2].column := 36;
for j := 1 to 24 do
begin
gotoxy(screen[0,1].column-2,screen[0,1].row+j-1); write('|');
gotoxy(screen[0,2].column-2,screen[0,2].row+j-1);write('|');
end;
for j := 1 to 32 do
begin
gotoxy(screen[1,0].column+j-2,screen[1,0].row-1);write('-');
gotoxy(screen[2,0].column+j-2,screen[2,0].row-1);write('-');
end;
end;
Procedure DrawSpot(Token,R,c:integer);
begin
case token of
Human:begin
textcolor(15);
gotoxy(screen[r,c].column,screen[r,c].row); write('XXXXXXX');
gotoxy(screen[r,c].column,screen[r,c].row+1); write('X X');
gotoxy(screen[r,c].column,screen[r,c].row+2); write('X X');
gotoxy(screen[r,c].column,screen[r,c].row+3); write('X X');
gotoxy(screen[r,c].column,screen[r,c].row+4); write('X X');
gotoxy(screen[r,c].column,screen[r,c].row+5); write('X X');
gotoxy(screen[r,c].column,screen[r,c].row+6); write('XXXXXXX');
end;
Computer:begin
Textcolor(4);
gotoxy(screen[r,c].column,screen[r,c].row); write('X X');
gotoxy(screen[r,c].column,screen[r,c].row+1); write(' X X ');
gotoxy(screen[r,c].column,screen[r,c].row+2); write(' X X ');
gotoxy(screen[r,c].column,screen[r,c].row+3); write(' X ');
gotoxy(screen[r,c].column,screen[r,c].row+4); write(' X X ');
gotoxy(screen[r,c].column,screen[r,c].row+5); write(' X X ');
gotoxy(screen[r,c].column,screen[r,c].row+6); write('X X');
end;
end;
delay(180); {adjust as desired}
end;
Procedure ScoreToken(rr,cc,Which:integer);
var
HCount:integer;
r,c:integer;
HowMuch:integer;
begin
Howmuch := 1 * Which;
Hcount := 0;
for c := 0 to 2 do
if game[rr,c] = Which then inc(Hcount);
if hcount = 2 then
for c := 0 to 2 do
inc(score[rr,c],howmuch);
hcount := 0;
for r := 0 to 2 do
if game[r,cc] = Which then inc(hcount);
if hcount = 2 then
for r := 0 to 2 do inc(score[r,cc],howmuch);
hcount := 0;
r := 0;
c := 0;
repeat
if game[r,c] = Which then inc(hcount);
inc(r);inc(c);
until r >2;
if hcount = 2 then
begin
r := 0;
c := 0;
repeat
inc(score[r,c],howmuch);
inc(r);inc(c);
until r >2;
end;
r := 0; c := 2;
hcount := 0;
repeat
if game[r,c] = Which then inc(hcount);
inc(r);dec(c);
until r > 2;
for c := 0 to 2 do
if (game[0,c] <> which) and (game[2,c] <> which)
and (game[0,c] <> 0) and (game[2,c] <> 0) then
for r := 0 to 2 do inc(score[r,c],which);
if hcount = 2 then
begin
r := 0;
c := 2;
repeat
inc(score[r,c],howmuch);
inc(r);dec(c);
until r >2;
end;
for r := 0 to 2 do
for c := 0 to 2 do
if game[r,c] <> 0 then score[r,c] := 0;
end;
Procedure Checkforwin(Who:integer);
var
r,c:integer;
count:integer;
begin
gameover := false;
wongame := false;
count := 0;
for r := 0 to 2 do
if (game[r,0] = who) and (game[r,1] = who) and (game[r,2] = who) then
wongame := true;
if not wongame then
for c := 0 to 2 do
if (game[0,c] = who) and (game[1,c] = who) and (game[2,c] = who)
then wongame := true;
if (game[0,0] = who) and (game[1,1] = who) and (game[2,2] = who) then
wongame := true;
if (game[0,2] = who) and (game[1,1] = who) and (game[2,0] = who) then
wongame := true;
if wongame then
begin
gotoxy(47,3);clreol;
gotoxy(47,3);
gameover := true;
textcolor(14);
Case who of
Computer:begin
Writeln('The X''s won');
inc(cwin);
end;
Human:begin
writeln('The O''s won');
inc(hwin);
end;
end;
end;
count := 0;
if not wongame then
begin
for r := 0 to 2 do
for c := 0 to 2 do
if game[r,c] <> 0 then inc(count);
Gameover := count = 9;
if gameover then
begin
textcolor(14);
inc(tie);
gotoxy(47,3);clreol;
gotoxy(47,3);write('Tie game!');
end;
end;
end;
procedure boardfix;
var
r,c:integer;
begin
{checks to make sure the scoring grid reflects where the players are. It zeros out player positions in the score matrix}
for r := 0 to 2 do
for c := 0 to 2 do
if game[r,c] <> 0 then score[r,c] := 0;
end;
Procedure HumanMove;
var
HCount:integer;
r,c:integer;
ch:char;
Goodmove:boolean;
begin
Goodmove := false;
repeat
Textcolor(7);
gotoxy(70,18);write('7 8 9');
gotoxy(70,19);write('4 5 6');
gotoxy(70,20);write('1 2 3');
ch := ' ';
repeat
gotoxy(70,21);write('Move:');
ch := readkey;
gotoxy(76,21);
if not (ch in goodinput) then beep(220,400)
else write(ch);
until ch in goodinput;
case ch of
'7','8','9':r := 0;
'4','5','6':r := 1;
'1','2','3':r := 2;
end;
case ch of
'7','4','1':c := 0;
'8','5','2':c := 1;
'9','6','3':c := 2;
end;
If game[r,c] = 0 then
begin
game[r,c] := Human;
Scoretoken(r,c,Human);
drawspot(Human,r,c);
goodmove := true;
end
else beep(220,400);
until goodmove;
boardfix;
checkforwin(Human);
end;
Procedure ComputerMove(Which:integer);
var
count:integer;
rr,cc,
r,c:integer;
mademove:boolean;
highspot:integer;
RandomNum:integer;
Procedure makemove(rr,cc:integer);
begin
mademove := true;
game[rr,cc] := Which;
scoretoken(rr,cc,Which);
drawspot(which,rr,cc);
end;
begin
boardfix;
count := 0;
mademove := false;
for r := 0 to 2 do
for c := 0 to 2 do
if game[r,c] <> 0 then inc(count);
{grab the middle early in the game}
if count <=3 then
if (game[1,1] = 0) and not mademove then
begin
r := 1; c := 1;
makemove(r,c);
end;
if not mademove then
if count <2 then
begin
mademove := false;
{Random corner grab is second}
repeat
randomnum := random(4);
case randomnum of
0: if game[0,0] = 0 then
begin
r := 0;
c := 0;
makemove(r,c);
end;
1:if (game[0,2] = 0 ) and not mademove then
begin
r := 0; c :=2;
makemove(r,c);
end;
2: if (game[2,0] = 0) and not mademove then
begin
r := 2; c := 0;
makemove(r,c);
end;
3:if (game[0,2] = 0) and not mademove then
begin
r := 0; c := 2;
makemove(r,c);
end;
end;
until mademove;
end
else
begin {Make a move based on score value - win first then block}
highspot := 0;
for r := 0 to 2 do
for c := 0 to 2 do
if score[r,c] > highspot then
begin
highspot := score[r,c];
rr := r; cc := c;
end;
if highspot > 0 then
begin
makemove(rr,cc);
r := rr; c := cc;
end
else
begin
{make a random move}
mademove := false;
repeat
r := random(3);
c := random(3);
until game[r,c] = 0;
makemove(r,c);
end;
end;
boardfix;
checkforwin(Which);
end;
begin
randomize;
hwin := 0;
Cwin := 0;
Tie := 0;
repeat
fillchar(game,sizeof(game),0);
fillchar(score,sizeof(score),0);
clrscr;
initscreen;
gameover := false;
wongame := false;
ac := random(2);
goesfirst := (ac = 0);
repeat
if not gameover then
if goesfirst then
humanmove
//computermove(Human) {the game can play itself}
else computermove(Computer);
boardfix;
if not gameover then
if goesfirst then
computermove(Computer)
else
Humanmove;
//computermove(Human);
boardfix;
if wongame then
begin
beep(220,180); beep(440,180); beep(880,180); {comment out for computer vs computer}
end;
until (gameover or wongame);
Textcolor(14);
gotoxy(40,1);clreol;
gotoxy(40,1);write('O''s wins:',Hwin,' *** X''s wins:',cwin,' *** Ties:',tie);
gotoxy(40,2);clreol;
gotoxy(40,2);write('Game over. Play again? y/n' );
EndingResponse := lowercase(readkey);
until EndingResponse <> 'y';
end.