125 lines
3.9 KiB
Ada
125 lines
3.9 KiB
Ada
with Ada.Text_IO, Ada.Numerics.Discrete_Random;
|
|
-- can play human-human, human-computer, computer-human or computer-computer
|
|
-- the computer isn't very clever: it just chooses a legal random move
|
|
|
|
procedure Tic_Tac_Toe is
|
|
|
|
type The_Range is range 1 .. 3;
|
|
type Board_Type is array (The_Range, The_Range) of Character;
|
|
|
|
package Rand is new Ada.Numerics.Discrete_Random(The_Range);
|
|
Gen: Rand.Generator; -- required for the random moves
|
|
|
|
procedure Show_Board(Board: Board_Type) is
|
|
use Ada.Text_IO;
|
|
begin
|
|
for Row in The_Range loop
|
|
for Column in The_Range loop
|
|
Put(Board(Row, Column));
|
|
end loop;
|
|
Put_Line("");
|
|
end loop;
|
|
Put_Line("");
|
|
end Show_Board;
|
|
|
|
function Find_Winner(Board: Board_Type) return Character is
|
|
-- if 'x' or 'o' wins, it returns that, else it returns ' '
|
|
|
|
function Three_Equal(A,B,C: Character) return Boolean is
|
|
begin
|
|
return (A=B) and (A=C);
|
|
end Three_Equal;
|
|
|
|
begin -- Find_Winner
|
|
for I in The_Range loop
|
|
if Three_Equal(Board(I,1), Board(I,2), Board(I,3)) then
|
|
return Board(I,1);
|
|
elsif Three_Equal(Board(1,I), Board(2,I), Board(3,I)) then
|
|
return Board(1,I);
|
|
end if;
|
|
end loop;
|
|
if Three_Equal(Board(1,1), Board(2,2), Board (3,3)) or
|
|
Three_Equal(Board(3,1), Board(2,2), Board (1,3)) then
|
|
return Board(2,2);
|
|
end if;
|
|
return ' ';
|
|
end Find_Winner;
|
|
|
|
procedure Do_Move(Board: in out Board_Type;
|
|
New_Char: Character; Computer_Move: Boolean) is
|
|
Done: Boolean := False;
|
|
C: Character;
|
|
use Ada.Text_IO;
|
|
|
|
procedure Do_C_Move(Board: in out Board_Type; New_Char: Character) is
|
|
Found: Boolean := False;
|
|
X,Y: The_Range;
|
|
begin
|
|
while not Found loop
|
|
X := Rand.Random(Gen);
|
|
Y := Rand.Random(Gen);
|
|
if (Board(X,Y) /= 'x') and (Board(X,Y) /= 'o') then
|
|
Found := True;
|
|
Board(X,Y) := New_Char;
|
|
end if;
|
|
end loop;
|
|
end Do_C_Move;
|
|
|
|
begin
|
|
if Computer_Move then
|
|
Do_C_Move(Board, New_Char);
|
|
else -- read move;
|
|
Put_Line("Choose your move, " & New_Char);
|
|
while not Done loop
|
|
Get(C);
|
|
for Row in The_Range loop
|
|
for Col in The_Range loop
|
|
if Board(Row, Col) = C then
|
|
Board(Row, Col) := New_Char;
|
|
Done := True;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
end loop;
|
|
end if;
|
|
end Do_Move;
|
|
|
|
The_Board : Board_Type := (('1','2','3'), ('4','5','6'), ('7','8','9'));
|
|
Cnt_Moves: Natural := 0;
|
|
Players: array(0 .. 1) of Character := ('x', 'o'); -- 'x' begins
|
|
C_Player: array(0 .. 1) of Boolean := (False, False);
|
|
Reply: Character;
|
|
|
|
begin -- Tic_Tac_Toe
|
|
|
|
-- firstly, ask whether the computer shall take over either player
|
|
for I in Players'Range loop
|
|
Ada.Text_IO.Put_Line("Shall " & Players(I) &
|
|
" be run by the computer? (y=yes)");
|
|
Ada.Text_IO.Get(Reply);
|
|
if Reply='y' or Reply='Y' then
|
|
C_Player(I) := True;
|
|
Ada.Text_IO.Put_Line("Yes!");
|
|
else
|
|
Ada.Text_IO.Put_Line("No!");
|
|
end if;
|
|
end loop;
|
|
Rand.Reset(Gen); -- to initalize the random generator
|
|
|
|
-- now run the game
|
|
while (Find_Winner(The_Board) = ' ') and (Cnt_Moves < 9) loop
|
|
Show_Board(The_Board);
|
|
Do_Move(The_Board, Players(Cnt_Moves mod 2), C_Player(Cnt_Moves mod 2));
|
|
Cnt_Moves := Cnt_Moves + 1;
|
|
end loop;
|
|
Ada.Text_IO.Put_Line("This is the end!");
|
|
|
|
-- finally, output the outcome
|
|
Show_Board (The_Board);
|
|
if Find_Winner(The_Board) = ' ' then
|
|
Ada.Text_IO.Put_Line("Draw");
|
|
else
|
|
Ada.Text_IO.Put_Line("The winner is: " & Find_Winner(The_Board));
|
|
end if;
|
|
end Tic_Tac_Toe;
|