在Tkinter中的函数内更改变量

时间:2018-10-22 23:07:27

标签: python class variables tkinter tic-tac-toe

我希望X和O动画在单击鼠标时来回切换。问题出在函数XorO中。我不太清楚为什么,但是单击它只会创建X。我认为这可能与我写转弯变量的方式有关。这就是我所拥有的。

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

2 个答案:

答案 0 :(得分:1)

这里的问题是,每次调用XsorOs方法时都会创建XorO对象。这意味着XsorOs.turn始终为1。 一种方法是从外部跟踪turn并使用global进行调用,但是使用 global中的“#”是应该避免的,尤其是它可能变得非常混乱。 我建议在Tk单独的“逻辑”类的自己的子类中跟踪turn

我为您提供了后者的示例:

(请注意,此示例非常草率(尤其是变量命名),应该只显示我的意思)

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

编辑:

  • lambda基本上是一种创建单行函数的方法。在这种情况下,我使用它通过事件函数传递参数。由于内部tkinter的作用类似于if that mouseclick happens do passed_function(event),因此您没有机会使用自己的参数。这就是lambda在这里有用的原因

  • __init__在这里可能不是那么重要,因为我看到人们之前在类主体中放置了变量,显然它可以正常工作,但是我个人更喜欢它在构造函数中创建类的所有变量。

  • self就像其他语言中的this一样,是对类或该类对象的引用(实际上,您可以通过命名第一个构造函数参数来按自己的方式命名,但是self是常用的)。它在类的范围内而不是在函数范围内“拉”变量。这意味着变量存在,只要对象存在,就可以对其进行操作。函数基本上在执行后会丢失所有内容。那是先前代码中的主要问题。

答案 1 :(得分:-1)

根据您对代码的一些调整,我设法修复了它。但是,我可以说,如果创建了X,则不能在同一图块上创建O和X?谢谢你的帮助。到目前为止,这就是我所拥有的。

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

此外,如果您有理由使用我在该评论中谈论的方法,请您解释一下原因。