CPTR 124 Fundamentals of Programming
In this lab you will write functions that control the logic of your 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
http://en.wikipedia.org/wiki/Tic-tac-toe provides the rules Tic-Tac-Toe. Your task is to provide the controlling logic for a two-player Tic-Tac-Toe computer game. This game engine should work independently of the application's presentation. It should be able to drive a modified version of your graphical Tic-Tac-Toe prototype, but also must work correctly for a non-graphical test program. 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 divide the code of 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 output), 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 by drawing a visual line across the three-in-a-row marks
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
Provide a dialog box that indicates the winner and gives the user the option to play again or quit
The presentation gets its information about what to display from the game engine, and the game engine gets 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:
tttlogic.py
(the game engine) andtictactoe.py
(the GUI—an adapted version of your previous assignment).- Game Logic. The file
tttlogic.py
is responsible for making the game work properly and enforcing the rules. Your job is to complete thetttlogic.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 docstrings and comments in the
tttlogic.py
Python module. The file contains the skeletal definitions of seven 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 first 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
. (You may elect to ignoremove
's return value in your GUI code, but your function should return the correct result regardless.)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'
).change_player
alternates the turn to the other player.set_player
forces the current player to be'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 seven functions above, you will need to add global variables in the
tttlogic.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.Important! Your
tttlogic.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 these statements when your work is complete. Also, yourtttlogic.py
should contain no Turtle graphics code. The game engine code should make no assumptions about how to show the user the progress of the game. It is the presentation's job (tictactoe.py
) to draw in the graphics window. - Presentation. Copy the file
tictactoe.py
from your previous assignment to a new folder. It must reside in the same folder as thetttlogic.py
file. Thetictactoe.py
Python source file is responsible for the presentation, and you must augment it to work with the game engine. Unlike with the code in thetttlogic
module, you have much freedom as to how you organize your functions and code withintictactoe.py
. You must, however, use graphics capabilities from theturtle
module only, with the exception of themessagebox
function that is found in thetkinter
module.The
tictactoe.py
file 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). Your original version oftictactoe.py
did not enforce the rules of the game, so it requires some modification to interact properly with the game engine.You will need to modify parts of your
tictactoe.py
file so it cooperates with the game engine. If you correctly implemented the mandated functions from the previous assignment (point_to_square
,square_to_point
,drawX
, anddrawO
), you should not have to touch these functions. Your prototype had to keep track of the current player, but now a global variable in thetttlogic
module will do this. Instead of blindly drawing a mark in a board position, your modified graphical application can do so only as allowed by the game engine. This means you will need to modify your function that processes mouse clicks.After each move, the function you registered with
onscreenclick
in the graphical application must do several things:- The function you registered with
onscreenclick
must check to see if the move was valid (viatttlogic.move
's return value) to determine if it should draw a mark in the selected square. If the move was valid, your graphical program can ask the game engine (viatttlogic.look
) which player owns the square in order to determine which mark to draw. If the move was not valid (for example, the player attempted to mark an already marked square), your GUI can show a message box that reports the failed move. The game engine can do this checking for you, so you should not do this work inside of your mouse clicked function.Note that your GUI does not have to keep track of whose turn it is—the game engine does that. Your GUI does maintain the ability to force the current player to be X or O via the keyboard as before, but users ordinarily do not exercise this power when playing Tic-Tac-Toe under the normal game rules.
- The function you registered with
onscreenclick
also must check (viatttlogic.check_status
) to see if a valid move resulted in a win or draw to determine if the game should continue. You will need to add code somewhere (most likely in a new function) that draws a line across the appropriate squares for a win or draws lines everywhere for a tie.
Another helpful function in the GUI would provide a way to initialize the presentation (necessarily calling
tttlogic.initialize_board
along the way). Your GUI would need to call this initialization function in between games to ensure all remnants of the previous game were cleared.In addition to augmenting your screen click callback, you will need to tweak the callback functions you wrote for pressing the X key and O key so that they properly cooperate with the services your
tttlogic
module provides. - The function you registered with
- Game Logic. The file
- 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 application consisting of your
tictactoe.py
andtttlogic.py
files will be evaluated for correctness and compliance. Double check to ensure the following:- that your
tttlogic.py
file contains no printing statements and no Turtle graphics code, and - that two players can play your graphical Tic-Tac-Toe game and things work as they would in the paper version.
Remember that your
tttlogic
module is intended to work with different presentations, not just yours; therefore, yourtttlogic.py
file will receive additional scrutiny. Follow the special instructions given during lab for the evaluation component. When approved, you should submit both Python source files 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