Skip to content Skip to sidebar Skip to footer

Changing Variables Within A Function In Tkinter

I want the X and O animations to switch back and forth upon mouse clicks. The problem is in the function XorO. I don't really understand why, but it will only create Xs when I clic

Solution 1:

The problem here is that the XsorOs object gets created every time you call the XorO method. This means XsorOs.turn is always 1. One way would be to keep track of turn from outside and call it with global but the use of global is something one should avoid especially it can get quite messy. I would recommend keeping track of turn within an own child class of Tk separate "logic" class

I made you an example for the latter:

(please note that this example is super sloppy (particularly the variable naming) and should just show you what I meant)

# stays the same until 'line4 = canvas.create_line(0, 400, 600, 400)'classXsorOs:
    def__init__(self):
        self.turn = 1defclick(self, row, col):
        if self.turn is (1or3or5or7or9):
            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)
        else:
            canvas.create_oval(col * third + 5, row * third + 5, (col + 1) * third - 5, (row + 1) * third - 5)
            self.turn += 1defmouse_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()

EDIT:

  • lambda is basically a way to create one line functions. In this case, I used it to pass arguments through the event function. Because somewhere internally tkinter does something like if that mouseclick happens do passed_function(event) so you have no chance to use your own arguments. That's why lambda is useful here

  • __init__ is maybe not that important here since I saw people putting variables in class bodies before and apparently it works just fine, but I personally prefer it to create all the variables of a class in the constructor

  • self is like this in other languages a reference to the class or the object of that class (you can actually name it the way you want by naming the first constructor argument, but self is commonly used). It "pulls" the variable in the scope of the class instead of the function. That means the variable exists and can be manipulated as long as the object exists. A function basically loses everything after execution. That was the main problem in your prior code.

Solution 2:

I managed to fix it based off a few tweaks from your code. However, I could I make it that if a X is created, an O and X cannot be created on that same tile? Thanks for your help. This is what I have so far.

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)


classXsorOs:
    def__init__(self):
        self.turn = 0
        self.clicked = []

    defclick(self, row, col):
        if (row, col) notin self.clicked
            if self.turn is0:
                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 += 1elif self.turn is1:
                canvas.create_oval(col * third + 5, row * third + 5, (col + 1) * third - 5, (row + 1) * third - 5)
                self.turn -= 1else:
                print("Game Over")
            self.clicked.append((row, col))


defmouse_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()

Also, if you have a reason to use the method you used that I was talking about in that comment, I would appreciate it if you would explain why.

Post a Comment for "Changing Variables Within A Function In Tkinter"