Place this file in a lab11 folder. Before leaving lab, zip up the lab11 folder and hand the zip file in.
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 the of a 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
See Canvas Commands for more info on drawing graphics.
In order to represent the state of play in a game of Tic-tac-toe, we will use a two-dimensional 3x3 array, where each element is None (if the corresponding position is unoccupied), 0 if the position is occupied by the mark ("O") of the first player ("Player 0"), or 1 if the position is occupied by the mark ("X") 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]]
my_window = tkinter.Tk() my_canvas = Canvas(my_window, width = 120, height = 120) my_canvas.pack() my_canvas.create_rectangle(0, 0, 90, 50, fill = "grey", width = 0) my_canvas.create_line(5, 45, 85, 5, width = 3) my_canvas.create_oval(75, 35, 85, 45, outline = "black", fill = "gray", width = 2) my_canvas.create_text(45, 70, text = "Hello world", anchor = "center", fill = "magenta")
input_num(prompt) and demonstrate how to use itn
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")
from random import randint def guessing_game(): pythons_number = randint(0, 2) num_guesses = 0 while True: num = input_num("Guess a number between 0 and 2, inclusive: ") num_guesses += 1 if pythons_number == num: print("You win! It took you " + str(num_guesses) + " guess(es)") return None print("Oops, you guessed wrong. Try again!")
Define a Python function display_grid(grid) that draws a game state to the Canvas. The following algorithm may be used for display_grid:
Note: tkinter is very exact with the coordinate system. For a more polished looking game, you can consider adding/subtracting offsets from coordinates to "shrink" the X's and O's
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. # my_canvas is the initialized canvas def draw_x(my_canvas, x0, y0, x1, y1): my_canvas.create_line(x0, y0, x1, y1, width = 3) my_canvas.create_line(x1, y0, x0, y1, width = 3)
The following usage should result in the image shown above:
>>>test_display()
In the starter code, tic_tac_toe.py, the functions check_win_horiz(grid, row) and check_win_diagonal1(grid) have been given to you. However, in order for the code to fully work, you must implement check_win_vert(grid, row) and check_win_diagonal2(grid) on your own. The descriptions for the functions are given below:
check_win_vert(grid, row) - returns True if any of the 3 columns in grid has all elements composed of all X's or all O's.
check_win_diagonal2(grid) - returns True if any of the elements in the backwards diagonal are all X's or all O's.
When you have completed these two functions, you should be able to play the game by calling play() in the Python Interpretter.