CPTR 124 Fundamentals of Programming
In this lab you will write functions that control the logic of a graphical Tic-Tac-Toe game.
- Teams
You are welcome to work with a partner on this lab. You and your partner should begin thinking about the problems and begin writing the code before lab time. You may work by yourself if you wish.
- What to do
For a background on the Tic-Tac-Toe game, see http://en.wikipedia.org/wiki/Tic-tac-toe. Your task is to provide the controlling logic for a graphical two-player Tic-Tac-Toe computer game. A game in progress might look like
Since it is a two-player game, your program does not play against a human opponent but simply allows the user(s) to interact with the board, making marks with the mouse.
We will divide the program into two separate components: the program logic and the presentation. The program logic forms the game engine, enforcing the rules of the game. The presentation is the interface to the user. The presentation can be graphical (pointing device and graphical screen), text based (keyboard input and text ouput), or something else, such as hand gestures, voice recognition, brain wave analysis, etc.
The following table shows some of the division of labor between the program logic and presentation:
Responsibilty of Engine
Responsibility of Presentation
Keep track of whose turn it is
Indicate the current player (X cursor or O cursor)
Keep track of the marks in each square
Indicate to the user the marks in each square (draw an X, O, or nothing)
Determine if there is a winner
Show the winning configuration as appropriate (highlight winning squares)
Disallow illegal moves
Provide feedback to user about an illegal move (display message box to user)
Place a mark in a specified position, if possible
Allow user to specify a move (process mouse clicks over the board)
Reset the game
Automatic after each game
The presentation gets all of its information about what to display from the game engine, and the game engine gets all of its input from the presentation.
We will implement this clean separation of control logic and presentation by writing a program that consists of two separate Python source files:
tictactoe.py
andttt_logic.py
.Presentation. The file
tictactoe.py
is responsible for the presentation. It provides a graphical user interface (GUI) that allows the user to make moves with a pointing device such as a mouse or touch pad. The GUI draws a natural looking Tic-tac-toe game board within a window (see the figure above). The filetictactoe.py
provides all the code to make to make the graphical interface work, so you should not touch any code within thetictactoe.py
file.Game Logic. The file
ttt_logic.py
is responsible for making the game work properly and enforcing the rules. Your job is to complete the ttt_logic.py file—in essence to program the rules of the game in Python. Some of the things your code must handle include- ignore illegal moves like trying to make a mark over an existing mark.
- control whose turn it is
- detect when the game is over (win or draw).
Study the comments in the
ttt_logic.py
Python module. The file contains the skeletal definitions of five functions. Observe that several of the functions accept string parameters and may return string results. It is important to use the exact strings specified in the comments so that the engine and the presentation can communicate successfully. The following is a comprehensive list of the strings the game engine and presentation use for communicating and making the game work:String
Meaning
Role
'X'
Player X or player X's mark
Player management
'O'
Player O or player O's mark
Player management
'NorthWest'
Top-left square
Board location
'North'
Top-middle square
Board location
'NorthEast'
Top-right square
Board location
'West'
Left-middle square
Board location
'Center'
Center square
Board location
'East'
Right-middle square
Board location
'SouthWest'
Bottom-left square
Board location
'South'
Bottom-middle square
Board location
'SouthEast'
Bottom-right square
Board location
'Playing'
No one has won and a move is available
Game state
'Win_NW_NE'
Win across top row
Game state
'Win_W_E'
Win across middle row
Game state
'Win_SW_SE'
Win across bottom row
Game state
'Win_NW_SW'
Win along left column
Game state
'Win_N_S'
Win along center column
Game state
'Win_NE_SE'
Win along right column
Game state
'Win_NW_SE'
Win from left-top corner to right-bottom corner
Game state
'Win_NE_SW'
Win from right-top corner to left-bottom corner
Game state
'Draw'
All squares filled with no winner
Game state
Your task is to implement the missing code in the functions and add global variables as needed to keep track of the state of the game.
look
expects a location string ('NorthWest'
,'North'
, etc.) as a parameter and returns the mark in that particular square ('X'
or'O'
) orNone
(if the square is empty). The graphical system uses thelook
function to determine what, if anything, to draw in a given square.move
puts the mark of a player ('X'
or'O'
) in a given square, if possible. The exact mark depends on the player with the current turn. A mark may be placed in a square only if the square is unoccupied. Themove
function requires its parameter to be one of the board location strings ('NorthWest'
,'North'
, etc.). If the move is a valid move, it addition to placing the mark, the function should ensure that turn transitions to the other player and finally returnTrue
If the attempted move is not valid, the function should not change the state of the game and simply returnFalse
.initialize_board
clears all marks off the board making it ready for a new game. It also makes player X the current player. The function should reset any data the program may be using to monitor or control the progress of a game.current_player
returns the player whose turn it is ('X'
or'O'
).check_status
determines if one player has won, the game is a draw, or if the game can continue. It returns a value the graphical system can use to render the board properly; for example, if player X has three marks in a line from the northeast corner of the board to the southwest corner as shown in the figure below,check_status
would return to the graphical interface the tuple('X', 'Win_NE_SW')
. The first element of the tuple is the winner, and the second element represents winning configuration. With this tuple the graphical interface in turn produces the presentation shown in the figure below. The playing and draw tuples would be(None, 'Playing')
and(None, 'Draw')
, respectively, as neither status involves a winner.The
check_status
function should not in any way alter the state of the game.
Think about it: If you can clear the board, put marks in specified squares, see what is in a given square, and check to see if the game is over or should continue, you have all the pieces necessary to model the control logic for a two-player Tic-Tac-Toe game.
In conjunction with implementing the five functions above, you will need to add global variables in the
ttt_logic.py
module that maintain the state of the game. Your functions will use and potentially modify these global variables as the game progresses. You need a variable to keep track of whose turn it is. You need nine variables that keep track of the marks assigned to each of the squares on the Tic-tac-toe board. You may want to add a variable to keep track of the number of moves during a game (so you can declare a draw if no one has won after nine moves)—although you can handle a tie in other ways. - Code Organization
Put
tictactoe.py
andttt_logic.py
in the same folder. Do not touchtictactoe.py
. You will work exclusively inttt_logic.py
. Implement the functions defined inttt_logic.py
. The comments inttt_logic.py
provide additional detail about what the functions do.Important! You should not modify the file
tictactoe.py
; it must be used as is. Also, yourttt_logic.py
file should contain NO input or output statements; that is,print
andinput
should not appear in your code. It is fine to use printing statements during development to help debug your code, but you should remove them when your work is complete. - Testing
When you are finished, thoroughly play with your Tic-Tac-Toe game, trying all combinations of moves, to ensure that your logic is correct. Does your code handle tie games properly? Does player X always have the first turn in a new game? If the very last move in a game uses the last available square but results in a win, does your code recognize the win or does it mistakenly report a draw?
- Check out
Your finished program will be evaluated for correctness and compliance. Double check to ensure the following:
- that your
ttt_logic.py
file contains no printing statements, - that your
ttt_logic.py
file executes properly with the unmodifiedtictactoe.py
file, and - that two players can play your graphical Tic-Tac-Toe game and things work as they would in the paper version.
Follow the special instructions given during lab for the evaluation component. When approved, you should submit your Python source file to http://eclass.e.southern.edu. Be sure your name (and your partner's name, if necessary) are included in comments at the top of each source file.
- that your