15-110 Summer Session Two - 2014

Lab 11 - Wednesday, July 30


Goals

In this lab you will focus on three different skills (1) how to draw shapes other than the rectangle (2) how to get input from the user of a program (3) how to write a component for a given program after studying its structure and behavior in a top-down fashion. When you are done, you should be able to do the following:

Deliverable

A file tic_tac_toe.py containing the diplay_grid() function along with the given starter code.

Place this file in a lab11 folder. Before leaving lab, zip up the lab11 folder and hand the zip file in.

TA Demonstration

  1. Review Canvas and introduce new Canvas primitives:
    from PythonLabs.Canvas import *
    Canvas.init(120, 120, "Lab10")
    Canvas.Line(5, 45, 85, 5, width = 3)
    Canvas.Text("Hello World", 45, 70, anchor = "center", fill = "magenta")
    
  2. Review the function

    input_num(prompt) and demonstrate how to use it

    def input_num(prompt):
        while True:
            s = input(prompt)
            if s == "quit": return 'quit'
            if s == "0": return 0
            if s == "1": return 1
            if s == "2": return 2
            print("input must be a number between 0 and 2 (inclusive) or quit")
    
    
  3. Review the function play() to observe how the given program for the game Tic-Tac-Toe is structured

Overview of Tic-Tac-Toe

In this lab, you will develop a program that allows two players to play Tic-tac-toe. In Tic-tac-toe, two players alternate placing their marks ("X"'s and "O"'s, respectively) in one of the 9 positions of a 3x3 grid. The first player to put three of their marks in a vertical, horizontal, or diagonal line is the winner. If nine marks have been placed without either player getting three marks in a row, the game ends in a tie.

Starter code: tic_tac_toe.py

In order to represent the state of play in a game of Tic-tac-toe, we will use a two-dimensional 3x3 list, where each element is None (if the corresponding position is unoccupied), 0 if the position is occupied by the mark ("X") of the first player ("Player 0"), or 1 if the position is occupied by the mark ("O") of the second player ("Player 1"). For example, the Tic-tac-toe grid shown at right could be represented by the 2d Python list:

[[1, None, 0], 
 [None, 0, None], 
 [None, None, None]]
The function new_grid creates the data representation for a blank 3x3 Tic-tac-toe grid. The function add_mark takes parameters grid, row, col, player, and modifies grid to place player's mark at the position specified by row and col as long as that position is unoccupied. If the position was unoccupied, then after modifying the grid, add_mark returns True. Otherwise (i.e., the position was already occupied), add_mark returns False.

Usage:

>>> grid = new_grid()
 [[None, None, None], [None, None, None], [None, None, None]]
>>> add_mark(grid,1,2,0)
 True
>>> grid
 [[None, None, None], [None, None, 0], [None, None, None]]
>>> add_mark(grid,1,2,1)
 False
>>> grid
 [[None, None, None], [None, None, 0], [None, None, None]]
>>> add_mark(grid,2,2,1)
 True
>>> grid
 [[None, None, None], [None, None, 0], [None, None, 1]]

Activities

  1. Graphical Display of Board State

    Define a Python function display_grid(grid) that draws a game state to the Canvas. The following algorithm may be used for display_grid:

    1. Create a Rectangle covering the entire 90x90 Canvas and filled with gray.
    2. Draw the horizontal and vertical lines separating the positions in the grid.
    3. For each grid position (rows in 0..2, columns in 0..2), do the following:
      1. Calculate the x, y coordinates of the center of that grid position.
      2. If the grid indicates that the position should hold an "O", then draw a circle centered at (x,y).
      3. If the grid indicates that the position should hold an "X" (i.e., grid[row][col] == 0), then draw an "X" at the correct coordinates.
      4. If the grid indicates that the position should hold neither an "X" nor an "O", then do the following:
        1. Create a string, consisting of the row, a comma, and the column. (Hint: You can convert the integer n to a string with str(n).)
        2. Place this string as "darkblue" text centered at (x,y).

    Hint: In implementing step C you can make use of the following function draw_x for drawing an "X".

    # x0, y0 are the coordinates of the top-left corner of the x.
    # x1, y1 are the coordinates of the bottom-right corner of the x.
    def draw_x(x0, y0, x1, y1):
    	Canvas.Line(x0, y0, x1, y1, width = 3)
    	Canvas.Line(x1, y0, x0, y1, width = 3)
    

    The following usage should result in the image shown above:

    >>> Canvas.init(90,90,"Lab11")
     True
    >>> display_grid([[1,None,0],[None,0,None],[None,None,None]])
    

  2. Checking for a Win

    Read through the Tic Tac Toe program and study how the check_win function works. It calls check_win_horiz and check_win_vert. Once you understand how it works, sit with another student and explain the function to each other so you are sure you both know how they work.

    Now, on your own, complete the functions check_win_diagonal1 and check_win_diagonal2. Test the game to see that your functions work correctly.

  3. Cleaning up the Code

    As you read through the function check_win, you should have had a feeling that there could be a shorter way to program that function (i.e. using fewer instructions). Revise that function to have as few lines of code as you possibly can.