CPTR 124 Fundamentals of Programming
What to do
In this lab you will rewrite your graphical Tic-Tac-Toe game so that it is object oriented.
For this assignment you must rewrite your
Tic-Tac-Toe code from an earlier assignment so that it
eliminates all global variables and free functions.
You will wrap your existing code within a class named
TicTacToeBoard
.
Create a new project
Create a new project and add the following three new files:
-
tttboard.h. You will add the
missing instance variables to the
TicTacToeBoard
class. -
tttboard.cpp. You will implement the
TicTacToeBoard
constructor and methods. -
tic_tac_toe.cpp. You will not modify
this file that contains the
main
function that creates and uses an instance of yourTicTacToeBoard
class.
As before, we identify the areas of the board by the
Square
enumeration types
(Square::Northwest
,
Square::North
, etc.) as shown in the
following table:
Square |
Meaning |
Role |
|
Top-left square |
Board location |
|
Top-middle square |
Board location |
|
Top-right square |
Board location |
|
Left-middle square |
Board location |
|
Center square |
Board location |
|
Right-middle square |
Board location |
|
Bottom-left square |
Board location |
|
Bottom-middle square |
Board location |
|
Bottom-right square |
Board location |
You should use nine instance variables to keep
track of the
mark corresponding to each of these locations (I called
mine nw
, n
, etc.). Each one of
these variables holds a Player
value. They
all start out with the value Player::None
to indicate at the beginning of the game no square holds
any marks.
You should use an instance variable to keep track of whose
turn it is (I called mine current_player
).
This variable holds a Player
value as
well—Player::X
or Player::O
.
In Tic-Tac-Toe X always has the first move.
These Square
and Player
types remain global, so they are assessable as is to
client code.
Your TicTacToeBoard
class
should enforce player
alternating turns and prevent a player from
placing a mark over an existing mark. Your code
also should detect a win or a draw. If a move results in a
win for one of the players, indicate the winning
configuration by drawing a line as shown here:
When the game results in a draw, draw lines everywhere, as shown here:
When a win or draw occurs the game is over, and no more moves are possible.
Your TicTacToeBoard
class must contain the
methods that appear in the skeletal
code:
-
point_to_square
. This private method accepts two parameters,x
andy
, representing the coordinates of a point on the game board. This function returns one of theSquare
values (Square::NorthWest
,Square::North
, etc. that represents a square on the board. In this method you need to supply code that maps a point to a particular square. Your method must return aSquare
value.The goal of this method is to be able to determine which square on the Tic-Tac-Toe game grid corresponds to a particular point in the graphics window. The user can click the mouse at multiple locations within a particular square, and all of those clicks should be treated the same. Your GUI will use this method to determine which square a player chose.
This method is private because clients have no need to call this method directly.
-
square_to_point
. This private method accepts one of theSquare
valuesSquare::NorthWest
,Square::North
, etc. and assigns to the reference variablesx
andy
the coordinates of the center of the corresponding square on your game board. This method does the reverse mapping ofpoint_to_square
.This method is useful when when drawing a player's mark on the game board: the lines that make up player X's mark cross at this point, and the circle that makes up player O's mark is centered at this point. You can draw an X by drawing two lines with the private
sgl::draw_line
method and draw a circle with thesgl::draw_circle
function.This method is private because clients have no need to call this method directly.
The two private methods
point_to_square
andsquare_to_point
work together. When the user clicks anywhere within a valid square on the Tic-Tac-Toe game board, the program can determine which square the user selected viapoint_to_square
. The game itself is concerned only with the nine square positions, not the thousands of possible pixel locations within the graphics window. Presented with a square, the program then can compute exactly where to center a player's mark for drawing. -
draw_player
. This private method acceptsPlayer
parameter and aSquare
parameter. It draws an X (two lines that cross) or an O (a circle) centered within the corresponding square on the game board. If the player value isPlayer::None
, this method does not draw anything.This method should use the
square_to_point
method to determine where the graphics code should draw the centered mark.This method is private because clients have no need to call this method directly.
-
Constructor
. The class constructor takes the place of the originalinitialize
function which no longer is needed. It sets all the instance variables to their initial state (all squares empty, and current player equal toPlayer::X
). -
draw
. This public method draws the game grid (four lines) and draws the player marks corresponding to each square usingdraw_player
.This method is public because the graphical frame must be able to call the method in order to redraw the window.
-
mouse_pressed
. This public method accepts two parameters that represent the (x, y) components of a point. It also accepts asgl::MouseButton
parameter, but your code can ignore it. This method will need to map the point it receives to its corresponding square. If the square is empty (check your global variable keeping track of this square), assign the current player's mark to this square and change the current player to the other player. If the square already has a mark, don't change square's mark and don't change the player.Finally (provided for you in the last line of the skeletal code), this method notifies the graphical framework via
sgl::window_update
to repaint the window so that it draws the new mark on the game board.This method is public because the graphical framework must call it when it detects a mouse pressed event.
You should not touch
the main
function.
Check out
Your finished program will be evaluated for correctness and compliance. Once you have been checked out you may submit your code to eclass.e.southern.edu.