Изменение переменных внутри функции в Tkinter - PullRequest
0 голосов
/ 23 октября 2018

Я хочу, чтобы анимации 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 голосов
/ 23 октября 2018

Мне удалось это исправить на основе нескольких настроек из вашего кода.Тем не менее, я мог бы сделать так, что если 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()

Кроме того, если у вас есть причина использовать метод, о котором я говорил в этом комментарии, я был бы признателен, если бы вы объяснили, почему.

0 голосов
/ 23 октября 2018

Проблема в том, что объект XsorOs создается каждый раз, когда вы вызываете метод XorO.Это означает, что XsorOs.turn всегда равно 1. Одним из способов будет отслеживание turn извне и вызов его с помощью global, но использование global - это то, чего следует избегать, особенно если оно может быть довольнобеспорядочный.Я бы порекомендовал отслеживать turn внутри собственного дочернего класса Tk, отдельного «логического» класса

Я сделал вам пример для последнего:

(обратите внимание, что этот пример супернебрежный (особенно имя переменной) и должен просто показать вам, что я имел в виду)

# 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).Он «вытягивает» переменную из области видимости класса вместо функции.Это означает, что переменная существует и может управляться, пока существует объект.Функция в основном теряет все после выполнения.Это было главной проблемой в вашем предыдущем коде.

...