Tic Tac Toe
Simple Tic Tac Toe game with crude graphics and no error checking.
Distribute this code freely, modify it, copy it I dont care. Mail me if you
ever find this useful.
------------------------------------------------------
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Integer_Text_IO;
use Ada.Integer_Text_IO;
-- Where we get the Randon generator
with Ada.Numerics.Discrete_Random;
procedure Tic_Tac_Toe is
------------------------Samir--------------------------------
-------------------------------------------------------------
---------------DECLARATIONS------------------------
-- 9 spaces in the tic tac toe board, max nine moves
subtype Looprange is Integer range 1..9;
-------------------------------------------------------------
subtype Choicerange is Integer range 1..2;
-- Subtype that limits certain input choices
-------------------------------------------------------------
-- For names of players
subtype Nametype is String(1..10);
-------------------------------------------------------------
-- Tic Tac Toe board range
subtype Boardrange is Positive range 1..3;
-------------------------------------------------------------
-- X and O are player or computer marks
-- E indicates Empty
type Gamesymbol is(X , O , E);
-------------------------------------------------------------
-- New IO for GameSymbol
package Symbol_IO is new Ada.Text_Io.Enumeration_IO(Enum =>
Gamesymbol);
-------------------------------------------------------------
-- Instantiate a package that generates random moves of BoardRange i.e
1..3
package RandomMove is new Ada.Numerics.Discrete_Random (BoardRange);
-------------------------------------------------------------
type Boardarray is array (Boardrange, Boardrange) of Gamesymbol;
-- The array for the board
-------------------------------------------------------------
type Playertype is
record
-- For each player
Name : Nametype; -- player name
Length : Positive; -- player name length
Playsymbol : Gamesymbol; -- symbol associated with player
end record; -- PlayerType
-------------------------------------------------------------
-- Variable used for making a choice
Continuechoice : Choicerange;
-------------------------------------------------------------
---------------------FUNCTIONS-----------------------------
-- Function that looks throught the gameboard and decides
-- if someone has won the game
-- Board: Game board
function Someone_Has_Won (Board : Boardarray;
Samevalue : Gamesymbol) return Boolean is
Result : Boolean; -- Value to be returned
begin -- Someone_Has_Won
Result := False; -- Initialize to game not yet over
for Column in Boardrange loop
-- Look through all three coloumns
if Board(1,Column)=Board(2,Column) and
Board(2,Column)=Board(3,Column) and
Board(3,Column)=Samevalue then
Result:=True;
end if; -- Board (1, Column)
end loop; -- FOR Column
for Row in Boardrange loop
-- Look through all three rows
if Board(Row,1)=Board(Row,2) and
Board(Row,2)=Board(Row,3) and
Board(Row,3)=Samevalue then
Result:=True;
end if; -- Board (Row,1)
end loop; -- FOR Row
if (Board(1,1)=Board(2,2) and -- Check leading diagonal
Board(2,2)=Board(3,3) and
Board(3,3)=Samevalue) or
(Board(3,1)=Board(2,2) and -- Check other diagonal
Board(2,2)=Board(1,3) and
Board(1,3)=Samevalue) then
Result:=True;
end if;
return Result;
end Someone_Has_Won;
-------------------------------------------------------------
-- Function to decide who moves first
function Whofirst (Player1 : Playertype;
Player2 : Playertype)return Boolean is
-- Declaring local variables here
Result : Boolean; -- Value to be RETURNed
Hewhomoves : Choicerange; -- Input Variable
begin --WhoFirst
Result := True; -- Initialise to player 1
New_Line; -- moves first
Put ("Who moves first?");
New_Line;
Put ("1. ");
Put (Player1.Name(1..Player1.Length));
New_Line;
Put ("2. ");
Put (Player2.Name(1..Player2.Length));
New_Line;
Get (Item => Hewhomoves);
-- If computer wants to move first
if Hewhomoves = 2 then
Result := False;
end if; -- HeWhoMoves = 2
return Result;
end Whofirst; -- function to decide who moves first
-------------------------------------------------------------
---------------------PROCEDURES-----------------------------
-- Procedure that asks players for their names
-- No1 : First player
procedure Get_Player_Name (No1 : OUT PlayerType;
No2 : OUT PlayerType) is
begin -- Get_Player_Name
Put ("Please enter your name");
New_Line;
Put ("Please make it brief and keep it under 10 characters");
New_Line;
Get_Line(No1.Name, No1.Length);
Put("What do you want to call your opponent?");
New_Line;
Get_Line(No2.Name,No2.Length);
-- Name of the first player
if No1.Length = 10 then -- If name of first player is
Skip_Line; -- more than 10 characters, truncate it
end if;
end Get_Player_Name; -- Get name input
-------------------------------------------------------------
-- Procedure that associates each player with a cross or a
-- circle, depending upon user choice
-- No1, No2 : Player and computer respectively
procedure Associate_Player_With_Symbol (
No1 : in out Playertype;
No2 : in out Playertype ) is
Symbolchoice : Integer; -- User input variable
begin -- Associate_Player_With_Symbol
Put ("What symbol would you like, ");
Put (No1.Name(1..No1.Length)); -- Ask player 1 which symbol
New_Line; -- he would prefer
Put ("1. Cross (X)");
New_Line;
Put ("2. Circle (O)");
New_Line;
Get (Item => Symbolchoice);
-- Input for getting user choice of symbols
if Symbolchoice = 1 then -- player 1 prefers cross
No1.Playsymbol := X; -- assign symbols accordingly
No2.Playsymbol := O;
else -- SymbolChoice = 2, player 1 prefers circle
No1.Playsymbol := O; -- Assign symbols accordingly
No2.Playsymbol := X;
end if; -- SymbolChoice = X
Put ("Now, "); -- confirm which player plays under
Put (No1.Name(1..No1.Length)); -- which symbol
Put (" is ");
Symbol_Io.Put (Item => No1.Playsymbol);
Put (" and ");
Put (No2.Name(1..No2.Length));
Put (" is ");
Symbol_Io.Put (Item => No2.Playsymbol);
end Associate_Player_With_Symbol;
-------------------------------------------------------------
-- Procedure that displays the game board after each move
-- Board : The game board that is to be displayed
-- A board with the new BoardArray type is created according to
-- user and computer inputs
procedure Display_Board (Board : in Boardarray ) is
Blank : constant String := " "; -- for empty place
Vert : constant String := "|"; -- boundaries of the
Horiz : constant String := "-"; -- gameboard
begin -- Display_Board
for I in 1..(2*(Boardrange'Last)+1) loop
Put (Horiz); -- Top boundary
end loop;
New_Line;
for I in Board'range(1) loop -- Loop first dimension
Put (Vert); -- vertical separator
for J in Board'range(2) loop -- Loop second dimension
if Board(I, J) = X or Board(I, J) = O then -- not empty
Symbol_Io.Put (Item =>Board (I, J));
elsif Board (I, J) = E then -- space is empty
Put (Blank);
end if; -- Board (I, J)
Put (Vert); -- vertical separator
end loop; -- FOR J
New_Line;
for I in 1..(2*(Boardrange'Last)+1) loop
Put (Horiz); -- Bottom boundary
end loop; -- FOR I
New_Line;
end loop; -- FOR J
end Display_Board;
-------------------------------------------------------------
-- Procedure that aks the player for coordinate of box
-- where the player's symbol is to be placed
-- Board : the game board
-- Mover : player whose turn it is to move
procedure Playermove (Board : in out Boardarray;
Mover : in Playertype) is
X : Boardrange; -- horizontal coordinate
Y : Boardrange; -- vertical coordinate
Correctchoice : Boolean; -- to make sure occupied spaces are not
overwritten
begin -- PlayerMove
Correctchoice := False; -- Initialize
New_Line;
Put (Mover.Name(1..Mover.Length)); -- ask player for input
Put (", please enter the box where you want to place your mark");
New_Line;
while not CorrectChoice loop
Put ("Enter the row in which you want your '");
Symbol_Io.Put (Item => Mover.Playsymbol);
Put ("' mark to be placed"); -- ask for row specification
New_Line;
Get (Y);
-- Input for row
Put ("Now please enter the coloumn you want it placed.");
New_Line; -- ask for coloumn specification
Get (X);
-- Input for coloumn
if Board (Y, X) = E then -- If space specified is empty
Board (Y, X):= Mover.Playsymbol;
Correctchoice := True;
else -- Space already occupied
Put ("You attempted to fill in a");
Put (" box that is already occupied");
New_Line;
end if; -- Board (Y, X)= E
end loop; -- While not CorrectChoice
end Playermove; -- Procedure to get player move
-------------------------------------------------------------
procedure ComputerMove(Board : IN OUT BoardArray;
Mover : IN PlayerType) is
X : Boardrange; -- horizontal coordinate
Y : Boardrange; -- vertical coordinate
Correctchoice : Boolean; -- to make sure occupied spaces are not
overwritten
-- Generate Random Values
RowGen : RandomMove.Generator;
ColGen : RandomMove.Generator;
begin
-- Initialize this value to false in the beginning
CorrectChoice := False;
while not CorrectChoice loop
RandomMove.Reset(RowGen);
RandomMove.Reset(ColGen);
X := RandomMove.Random(RowGen);
Y := RandomMove.Random(ColGen);
-- Input for coloumn
if Board (X, Y) = E then -- If space specified is empty
Board (X, Y):= Mover.Playsymbol;
Correctchoice := True;
end if; -- Board (Y, X)= E
end loop; -- While not CorrectChoice
end ComputerMove;
-------------------------------------------------------------
-- Procedure that acts like a base for the whole game
-- other procedures branch off from Play_Game
procedure Play_Game is
Empty : constant Gamesymbol := E; -- Empty space
Gameboard : Boardarray; -- The game board
Player1 : PlayerType; -- Player1
Player2 : PlayerType; -- Computer
Mover : Playertype; -- The player whose turn
it is to move
PlayerTurnCount : Boolean; -- Counter variable for
the loop
Loopcount : Positive; -- To determine whose
turn it is
begin -- Play Game
Gameboard := (others => (others => Empty)); -- Initialize
GameBoard to fully empty
-- Procedure to get name of players
Get_Player_Name (No1=>Player1, No2=>Player2);
-- Procedure to associate each player with a symbol
Associate_Player_With_Symbol (No1 => Player1, No2 => Player2);
-- Call on WhoFirst to find who moves first
PlayerTurnCount := Whofirst(Player1, Player2);
-- Display empty board
Display_Board(Board => Gameboard);
for I in Looprange loop
-- GAME LOOP
-- A maximum of 9 spaces to be filled
Loopcount := I;
if PlayerTurnCount = True then -- to find whose turn it is
Mover := Player1;
else -- PlayerTurnCount = False
Mover := Player2;
end if; -- PlayerTurnCount = True
if Mover = Player1 then
-- Procedure that asks Player to move
Playermove (Board => Gameboard, Mover => Mover);
else
ComputerMove(Board=> GameBoard, Mover => Mover);
end if;
-- Display board after move
Display_Board(Board => Gameboard);
-- Condition for loop exit
exit when Someone_Has_Won(Gameboard, Mover.Playsymbol);
Playerturncount := not Playerturncount; -- Change of player
end loop; -- FOR I
if Someone_Has_Won(Gameboard, Mover.Playsymbol ) then
Put(Mover.Name(1..Mover.Length));
Put(" has won.");
New_Line;
-- IF game was ended after all spaces were filled
elsif NOT Someone_Has_Won(Gameboard,Mover.Playsymbol)
AND Loopcount = Looprange'Last then
Put ("The game is drawn");
end if;
end Play_Game; -- Base procedure off which others branch
-------------------------------------------------------------
begin -- Main Program Tic_Tac_Toe
loop -- ContinueChoice loop
Play_Game; -- Call on Play_Game to play
New_Line;
Put ("1. Play Again"); -- after game end, ask players
New_Line; -- if they want another game
Put ("2. Quit");
New_Line;
Put ("Please enter your choice");
Get (Continuechoice);
-- Input for ContinueChoice
if Continuechoice = 2 then -- IF players want to quit
New_Line;
exit;
end if; -- Choice = 2
Skip_Line;
end loop; -- end ContinueChoice
end Tic_Tac_Toe;
Contributed by: Samir
Contributed on: December 7, 2001
License: Public Domain
Back