You will be supplied a class template and a driver function which will play the game (below). You will have to fill in some other code including some constants, class methods, and possibly some subsidiary functions. Below is the template and driver. This is also in the following file: Tic Tac Toe template. Note that the board is simply a 2D (3x3) list of characters (" ", "X", "O"); this makes it pretty simple to print.
With each human move, you should ensure that the move is legal: has form r, c where r and c are in the range [0..2]. You can assume that r and c are integers, but not that they are in the correct range. Spaces shouldn't matter. Also, check that the selected space isn't already occupied. Machine moves are guaranteed to be legal.
import random # Some global constants: HUMAN = 0 MACHINE = 1 YOU_WON = "Congratulations! You won!\n" ... other constants (see the driver and output). def initialBoard(): return [ [" ", " ", " "], \ [" ", " ", " "], \ [" ", " ", " "] ] class TicTacToe: def __init__(self): # Initialize the game with the board and current player def __str__(self): # Return a string representation of the board. def getPlayer( self ): # Return the current player. def isWin( self ): # See if the board represents a win for the current # player. A win is three of the current player's tokens # in a single row, column, or either diagonal. def swapPlayers( self ): # Change the current player from HUMAN to MACHINE or # vice versa. def humanMove( self ): # Ask the HUMAN to specify a move. Check that it's # valid (syntactically, in range, and the space is # not occupied). Update the board appropriately. def machineMove( self ): # This is the MACHINE's move. It picks squares randomly # until it finds an empty one. Update the board appropriately. # Note: this is a really dumb way to play tic-tac-toe. print("Machine's turn:") while True: r = random.randint(0, 2) c = random.randint(0, 2) if self.__board[r][c] == " ": print(" Machine chooses: ", r, ", ", c, sep="") self.__board[r][c] = "O" return def driver( ): """ This plays tic-tac-toe in a pretty simple-minded fashion. The human player goes first with token "X" and alternates with the machine using token "O". We print the board before the first move and after each move. """ # Print the welcome message print( WELCOME ) # Initialize the board and current player ttt = TicTacToe() print( ttt ) # There are up to 9 moves in tic-tac-toe. for move in range(9): # The current player may be HUMAN # or MACHINE if ttt.getPlayer() == HUMAN: # If HUMAN, take a move, print the board, # and see if it's a win. ttt.humanMove() print( ttt ) if ttt.isWin(): print( YOU_WON ) return else: # Else MACHINE takes a move. Print the # board and see if the machine won. ttt.machineMove() print( ttt ) if ttt.isWin(): print( YOU_LOST ) return # Swap players. ttt.swapPlayers() # After nine moves with no winner, it's a tie. print( YOU_TIED ) driver()Notice that this is a pretty dumb way to play tic-tac-toe.
> python Project2.py Welcome to our Tic-Tac-Toe game! Please begin playing. | | ----- | | ----- | | Your turn: Specify a move r, c: 9, 2 Illegal move specified. Try again! Specify a move r, c: 0 0 Response should be r, c. Try again! Specify a move r, c: 0, 0 X| | ----- | | ----- | | Machine's turn: Machine chooses: 1, 0 X| | ----- O| | ----- | | Your turn: Specify a move r, c: 2, 0 X| | ----- O| | ----- X| | Machine's turn: Machine chooses: 2, 2 X| | ----- O| | ----- X| |O Your turn: Specify a move r, c: 1,2 X| | ----- O| |X ----- X| |O Machine's turn: Machine chooses: 0, 2 X| |O ----- O| |X ----- X| |O Your turn: Specify a move r, c: 1, 1 X| |O ----- O|X|X ----- X| |O Machine's turn: Machine chooses: 0, 1 X|O|O ----- O|X|X ----- X| |O Your turn: Specify a move r, c: 2, 1 X|O|O ----- O|X|X ----- X|X|O Looks like a tie. Better luck next time! > python Project2.py Welcome to our Tic-Tac-Toe game! Please begin playing. | | ----- | | ----- | | Your turn: Specify a move r, c: 3 3 Response should be r, c. Try again! Specify a move r, c: 3, 3 Illegal move specified. Try again! Specify a move r, c: 0, 0 X| | ----- | | ----- | | Machine's turn: Machine chooses: 2, 2 X| | ----- | | ----- | |O Your turn: Specify a move r, c: 2, 0 X| | ----- | | ----- X| |O Machine's turn: Machine chooses: 1, 2 X| | ----- | |O ----- X| |O Your turn: Specify a move r, c: 0, 1 X|X| ----- | |O ----- X| |O Machine's turn: Machine chooses: 1, 1 X|X| ----- |O|O ----- X| |O Your turn: Specify a move r, c: 2, 1 X|X| ----- |O|O ----- X|X|O Machine's turn: Machine chooses: 0, 2 X|X|O ----- |O|O ----- X|X|O Sorry! You lost! > python Project2.py Welcome to our Tic-Tac-Toe game! Please begin playing. | | ----- | | ----- | | Your turn: Specify a move r, c: 1, 1 | | ----- |X| ----- | | Machine's turn: Machine chooses: 0, 2 | |O ----- |X| ----- | | Your turn: Specify a move r, c: 0, 0 X| |O ----- |X| ----- | | Machine's turn: Machine chooses: 2, 2 X| |O ----- |X| ----- | |O Your turn: Specify a move r, c: 2, 1 X| |O ----- |X| ----- |X|O Machine's turn: Machine chooses: 2, 0 X| |O ----- |X| ----- O|X|O Your turn: Specify a move r, c: 0, 1 X|X|O ----- |X| ----- O|X|O Congratulations! You won! >
Functions are one of your most useful tools for managing the complexity of code. Strictly speaking, you can get by without them. But your code is likely to be an unreadable, unmaintainable jumble. Consider the question of whether the tic-tac-toe player who just placed a token on the board thereby won the game. She did if there are now three of her tokens in a row, either within one row of the board, one column of the board, or either of the two diagonals.
As an experienced programmer and someone who appreciates the value of functional abstraction, my natural inclination is to write the following auxiliary function:
def isWin( board, token ): return isRowWin( board, token ) \ or isColumnWin( board, token ) \ or isDiagonalWin( board, token )And then go off and write the other three functions isRowWin, isColumnWin, and isDiagonalWin. And yes, I could write one big complicated expression involving lots of ands, ors, and indexes into the board. But I'd be much less sure that it was correct. Having broken it up into a series of simple functions, it's much easier to see that I'm doing it right.
Students often think that writing functions is a waste of time; they're wrong. Just the increase in clarity is well worth the effort.
Your file must compile and run before submission. It must also contain a header with the following format:
# File: Project2.py # Student: # UT EID: # Course Name: CS303E # # Date: # Description of Program: