Tkinter Ti c Ta c Toe: Добавление в состоянии ie, привязка к клавишам, остановка игры без закрытия холста - PullRequest
0 голосов
/ 19 января 2020

Поскольку проект Ti c Ta c Toe почти завершен, у меня возникло несколько проблем, связанных с привязкой и добавлением в состоянии ie. Я могу связать функции с и они работают нормально, но я хочу, чтобы они были связаны с R и escape-ключом (reset_game для R и близко к escape). Я также попытался добавить переменную k для условия t ie, но он говорит, что это не было определено. Вот код:

from tkinter import *
import tkinter.messagebox
ttt = Tk()
ttt.title("Tic Tac Toe")
w = Canvas(ttt, width = 902, height = 902)
w.configure (bg =  "white")
w.pack()

m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
size = 300
player = 1


w.create_line(0, 300, 902, 300, fill = "black") 
w.create_line(0, 601, 902, 601, fill = "black")
w.create_line(300, 0, 300, 902, fill = "black")
w.create_line(601, 0, 601, 902, fill = "black")

def on_click(event):
    global m
    global player
    global k
    row = event.y // size
    col = event.x // size
    if m[row][col] == 0:
        cx = col * size + size // 2
        cy = row * size + size // 2
        if player == 1:
            draw_X(cx, cy)
            print ("Player 1, X")
        else:
            draw_O(cx, cy)
            print ("Player 2, O")
        m[row][col] = player
        Win()
        player = 2 if player == 1 else 1
    k = k + 1

def draw_O(x, y):
    radius = size // 3
    w.create_oval(x-radius, y-radius, x+radius, y+radius, width=5, tag='cell')

def draw_X(x, y):
    radius = size // 3
    w.create_line(x-radius, y-radius, x+radius, y+radius, width=5, tag='cell')
    w.create_line(x+radius, y-radius, x-radius, y+radius, width=5, tag='cell')

def reset_game(event):
    global m
    global player
    w.delete('cell')
    m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    player = 1
    k = 0

def tie():
    if (k==8):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Tie")

def Win():
    if (m[0][0] == m[0][1] and m[0][0] == m[0][2] and m[0][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][0]))
        ttt.destroy()
        print ("Player", str(m[0][0]), "wins")
    elif (m[0][0] == m[1][0] and m[0][0] == m[2][0] and m[0][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][0]))
        ttt.destroy()
        print ("Player", str(m[0][0]), "wins")
    elif (m[1][0] == m[1][1] and m[1][0] == m[1][2] and m[1][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[1][0]))
        ttt.destroy()
        print ("Player", str(m[1][0]), "wins")
    elif (m[0][1] == m[1][1] and m[0][1] == m[2][1] and m[0][1]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][1]))
        ttt.destroy()
        print ("Player", str(m[0][1]), "wins")
    elif (m[0][2] == m[1][2] and m[0][2] == m[2][2] and m[0][2]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][2]))
        ttt.destroy()
        print ("Player", str(m[0][2]), "wins")
    elif (m[2][0] == m[2][1] and m[2][0] == m[2][2] and m[2][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[2][0]))
        ttt.destroy()
        print ("Player", str(m[2][0]), "wins")
    elif (m[0][0] == m[1][1] and m[0][0] == m[2][2] and m[0][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][0]))
        ttt.destroy()
        print ("Player", str(m[0][0]), "wins")
    elif (m[0][2] == m[1][1] and m[0][2] == m[2][0] and m[0][2]):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][2]))
        ttt.destroy()
        print ("Player", str(m[0][2]), "wins")


w.bind('<Button-1>', on_click)

def close(event):
    ttt.destroy()

w.bind('<Button-2>',close)

w.bind('<Button-3>', reset_game)

ttt.mainloop()

Я также хочу остановить игру после того, как кто-то выиграет или будет на ie, не закрывая холст, чтобы я мог сбросить. Есть идеи как это сделать?

1 Ответ

1 голос
/ 20 января 2020

Поскольку вы добавили глобальную переменную k в качестве числа сыгранных ходов, player можно определить по значению k, чтобы ее можно было удалить из глобальных переменных.

Вам необходимо объявить глобальную переменную k:

m = [[0,0,0], [0,0,0], [0,0,0]]
size = 300
k = 0

Также вы можете упростить / изменить функцию Win, чтобы принимать row и col в качестве аргументов и возвращать, есть ли победитель:

 def Win(row, col):
    # check horizontal
    if m[row][0] == m[row][1] == m[row][2]:
        return m[row][col]
    # check vertical
    if m[0][col] == m[1][col] == m[2][col]:
        return m[row][col]
    # check diagonals
    cell = (row, col)
    if cell in ((0,0), (1,1), (2,2)) and m[0][0] == m[1][1] == m[2][2]:
        return m[row][col]
    if cell in ((2,0), (1,1), (0,2)) and m[2][0] == m[1][1] == m[0][2]:
        return m[row][col]
    # no winner, returns None
    return None

Затем измените on_click функцию:

def on_click(event):
    global m
    global k
    row = event.y // size
    col = event.x // size
    if m[row][col] == 0:
        cx = col * size + size // 2
        cy = row * size + size // 2
        # determine current player
        player = 1 + k % 2
        if player == 1:
            draw_X(cx, cy)
            print("Player 1, X")
        else:
            draw_O(cx, cy)
            print("Player 2, O")
        m[row][col] = player
        k += 1
        # only need to check winner after 5 turns
        if k >= 5:
            winner = Win(row, col)
            msg = None
            if winner:
                msg = "Winner is player {}: {}".format(player, 'X' if player == 1 else 'O')
            elif k == 9:
                msg = "Tie game"
            if msg:
                tkinter.messagebox.showinfo("Tic Tac Toe", msg)
                reset_game()

Для ключей привязки:

w.bind('<Escape>', lambda e: ttt.destroy())
w.bind('R', reset_game)
w.bind('r', reset_game)
w.focus_set()   # Canvas need to get the focus in order to get the keyboard events
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...