Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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 click it. I think it may have to do with how I wrote the turn variable. Here is what I have.

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)



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

def XorO(row,col):
    class XsorOs:
        turn = 1
        if turn is (1 or 3 or 5 or 7 or 9):
            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)
        turn += 1

canvas.pack()
canvas.bind("<Button-1>", mouse_click)
canvas.mainloop()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
116 views
Welcome To Ask or Share your Answers For Others

1 Answer

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)'
class XsorOs:
    def __init__(self):
        self.turn = 1

    def click(self, row, col):
        if self.turn is (1 or 3 or 5 or 7 or 9):
            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 += 1


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

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...