Tic Tac Toe (3)

In today’s lecture, we will continue our discussion on building a simple text-based board game (Tic Tac Toe). In the process, we will learn about the benefits of inheritance, encapsulation and more generally of object-oriented design.

Tic Tac Toe Letter

Last time we looked at TTTBoard, which inherits from Board and also adds Tic Tac Toe specific features. Today we’ll look at the final two classes: TTTLetter and TTTGame.

# TTTLetter class
"""Implements the functionality of a letter in Boggle."""

from graphics import *

class TTTLetter:
    """A TTT letter has several attributes that define it:
           *  _row, _col coordinates indicate its position in the grid (ints)
           *  _textObj denotes the Text object from the graphics module,
              which has attributes such as size, style, color, etc
              and supports methods such as getText(), setText() etc.
    """

    __slots__ = ['_row', '_col', '_textObj']

    def __init__(self, win, col=-1, row=-1, letter=""):

        # global variables needed for graphical testing
        xInset = 50; yInset = 50; size = 50

        # set row and column attributes
        self._col = col
        self._row = row

        self._textObj = Text(Point(xInset + size * col + size / 2,
                                  yInset + size * row + size / 2), letter)

        self._textObj.setSize(20)
        self._textObj.setStyle("bold")
        self._textObj.setTextColor("black")
        self._textObj.draw(win)

    def getLetter(self):
        """Returns letter (text of type str) associated with property textObj"""
        return self._textObj.getText()

    def setLetter(self, char):
        self._textObj.setText(char)

    def __str__(self):
        l, col, row = self.getLetter(), self._col, self._row
        return "{} at Board position ({}, {})".format(l, col, row)

    def __repr__(self):
        return str(self)
    
win = GraphWin("Tic Tac Toe", 400, 400)

letter = TTTLetter(win, 1, 1, "X")
letter2 = TTTLetter(win, 1, 2, "O")
letter3 = TTTLetter(win, 2, 1, "X")

letter2.setLetter("T")
print(letter2)
win.close()

Tic Tac Toe Game

Finally, let’s put it all together and implement the game logic in TTTGame.

"""Implements the logic of the game of tic tac toe."""

from graphics import GraphWin
from tttboard import TTTBoard
from tttletter import TTTLetter

class TTTGame:
    __slots__ = [ "_board", "_numMoves", "_player" ]

    def __init__(self, win):
        self._board = TTTBoard(win)
        self._player = "X"
        self._numMoves = 0

    def doOneClick(self, point):
        """Implements the logic for processing one click.
        Returns True if play should continue, and False if the 
        game is over."""
        
        # step 1: check for exit button and exit
        if self._board.inExit(point):
            # game over
            return False

        # step 2: check for reset button and reset game
        elif self._board.inReset(point):
            self._board.reset()
            self._board.clearUpperText()
            self._numMoves = 0
            self._player = "X"

        # step 3: check if click is on a cell in the grid
        elif self._board.inGrid(point):
            tlet = self._board.getTTTLetterAtPoint(point)

            # make sure this square is vacant
            if tlet.getLetter() == "":
                tlet.setLetter(self._player)

                # valid move, so increment numMoves
                self._numMoves += 1

                # check for win or draw
                winFlag = self._board.checkForWin(self._player)
                if winFlag:
                    self._board.setStringToUpperText(self._player + " WINS!")
                elif self._numMoves == 9:
                    self._board.setStringToUpperText("DRAW!")
                # not a win or draw, swap players
                else:
                # set player to X or O
                    if self._player == "X":
                        self._player = "O"
                    else:
                        self._player = "X"
        # keep going!
        return True
win = GraphWin("Tic Tac Toe", 400, 400)
game = TTTGame(win)
keepGoing = True
while keepGoing:
    point = win.getMouse()
    keepGoing = game.doOneClick(point)
win.close()