2

I am making tic tac toe game in Tkinter and it currently works, but I want the code to recognize when a range in the window (ex. 0, 0, 200, 200) is clicked so that I can change the variable. The goal with this is to make the game know when there is three in a row. My problem (as you can see in line 28 - 29, if self.clicked...) is trying to make a variable (or other solution) that will make boxes in the window have a value of 0 or 1 depending on whether they have been clicked. Please help.

from tkinter import *


tk = Tk()
width = 600
third = width / 3
canvas = Canvas(width=width, height=width)
tk.title = "Tic Tac Toe"


line1 = canvas.create_line(200, 0, 200, 600)
line2 = canvas.create_line(400, 0, 400, 600)
line3 = canvas.create_line(0, 200, 600, 200)
line4 = canvas.create_line(0, 400, 600, 400)


class XsorOs:
    def __init__(self):
        self.turn = 0
        self.clicked = []

    def click(self, row, col):
        if (row, col) not in self.clicked:
            if self.turn is 0:
                canvas.create_line(col * third, row * third, (col + 1) * third, (row + 1) * third)
                canvas.create_line((col + 1) * third, row * third, col * third, (row + 1) * third)
                self.turn += 1
                if self.clicked in range(0, 0, 200, 200):
                    print('hi')

            elif self.turn is 1:
                canvas.create_oval(col * third + 5, row * third + 5, (col + 1) * third - 5, (row + 1) * third - 5)
                self.turn -= 1
            else:
                print("Game Over")
            self.clicked.append((row, col))


def mouse_click(c, event):
    col = int(event.x / third)
    row = int(event.y / third)
    c.click(row, col)


xo = XsorOs()
canvas.pack()
canvas.bind("<Button-1>", lambda event: mouse_click(xo, event))
canvas.mainloop()

The print hi is just a placeholder until I figure out how to do it. I want that to become "make this part of the window 1 (from 0)."

B S
  • 100
  • 1
  • 2
  • 7

1 Answers1

0

I suggest using a 3x3 array to store data and then use some if statements to detect the 3 in a row. I remember creating Tic-Tac-Toe in tkinter and this is the method I used.

from tkinter import *

tk = Tk()
width = 600
third = width / 3
canvas = Canvas(width=width, height=width)
tk.title = "Tic Tac Toe"

line1 = canvas.create_line(200, 0, 200, 600)
line2 = canvas.create_line(400, 0, 400, 600)
line3 = canvas.create_line(0, 200, 600, 200)
line4 = canvas.create_line(0, 400, 600, 400)

game_board = [['' for x in range(3)] for y in range(3)]

class XsorOs:
    def __init__(self):
        self.turn = 0
        self.clicked = []
    def click(self, row, col):
        if (row, col) not in self.clicked:
            if self.turn % 2 == 0:
                canvas.create_line(col * third, row * third, (col + 1) * third, (row + 1) * third)
                canvas.create_line((col + 1) * third, row * third, col * third, (row + 1) * third)
                self.turn += 1
                game_board[row][col] = 'x'

            elif self.turn % 2 == 1:
                canvas.create_oval(col * third + 5, row * third + 5, (col + 1) * third - 5, (row + 1) * third - 5)
                self.turn += 1
                game_board[row][col] = 'o'
        ## add some if statements to detect diagonals, horizontals and verticals in a row.

def mouse_click(c, event):
    col = int(event.x / third)
    row = int(event.y / third)
    c.click(row, col)


xo = XsorOs()
canvas.pack()
canvas.bind("<Button-1>", lambda event: mouse_click(xo, event))
canvas.mainloop()
  • How would I detect these? I tried it with this, but it did not work. if game_board[row][col] is 'x' in range(1, 1) and game_board[row][col] is 'x' in range(1, 2) and game_board[row][col] is 'x' in range(1, 3): canvas.create_line(0, 100, 600, 100) – B S Oct 24 '18 at 01:43
  • Sorry for writing it like that I couldn't figure out how to format code in comments. If you could give an example for detecting a horizontal 1st row that would be very helpful. Also, shouldn't it be for x in range of 2 because it starts at 0? – B S Oct 24 '18 at 01:54
  • Horizontal lines are very easy, have a loop for x with a range of 3 then have `if game_board[x][0] == 'x' and game_board[x][1] == 'x' and game_board[x][2] == 'x': do_things()` – Goldman Lee Oct 24 '18 at 03:30
  • FYI use the quote looking symbols left of the '1' key to turn your comments into code. – Goldman Lee Oct 24 '18 at 03:34
  • Thanks. So does that mean it is supposed to be `game_board = [['' for x in range(3)] for y in range(3)]` and not `game_board = [['' for x in range(2)] for y in range(2)]` because don't arrays / lists start at 0 so with `range(2)` it would actually be three? – B S Oct 24 '18 at 03:58
  • No, `for i in range(n)` is equal to C++'s `for (int i = 0; i < n; i++)` which means the iteration ends before it reaches n, therefore `for i in range(3)` loops 3 times. – Goldman Lee Oct 24 '18 at 06:35