Ткинтер Ti c Ta c Toe Рисование фигуры в определенной коробке - PullRequest
2 голосов
/ 10 января 2020

Я новичок ie в программировании, пытаюсь выучить python, и я решил сделать Ti c Ta c Toe для моего первого проекта. Я создал функции для рисования X и O, но у меня возникли проблемы с их отображением в поле, которое я нажимаю Вот код на данный момент:

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]]

def drawx(event):
    x, y = event.x, event.y
    w.create_line(49, 49, 249, 249, fill = "black")
    w.create_line(49, 249, 249, 49, fill = "black")

def drawo(event):
    x2, y2 = event.x, event.y
    x0 = x2 - 100
    y0 = y2 - 100
    x1 = x2 + 100
    y1 = y2 + 100
    return w.create_oval(x0, y0, x1, y1)

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

Здесь фигуры будут нарисованы на основе моих координат курсора, которые, как я знаю, должны быть изменены. Буду признателен за любую помощь или предложение.

Ответы [ 3 ]

2 голосов
/ 10 января 2020

Вы можете "дискретизировать" значения x и y путем целочисленного деления, а затем умножения на ширину отдельных ячеек (и добавления некоторого смещения для центра).

def drawo(event):
    x2, y2 = event.x, event.y
    x2 = x2 // 300 * 300 + 150
    y2 = y2 // 300 * 300 + 150
    ...

То же самое для drawx.

В качестве альтернативы, вы можете использовать разные элементы холста (или кнопки, метки или аналогичные) для разных ячеек в сетке и получить нажатый widget из event.

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

Вам необходимо привязать событие щелчка мыши к холсту:

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

Затем определите, какая ячейка была нажата в обработчике on_click:

SIZE = 300
player = 1  # 1 for O, 2 for X

def on_click(event):
    global m
    global player
    row = event.y // SIZE
    col = event.x // SIZE
    # check whether the cell is not filled yet
    if m[row][col] == 0:
        # calculate the center of the cell
        cx = col * SIZE + SIZE // 2
        cy = row * SIZE + SIZE // 2
        # draw X or O based on current player
        if player == 1:
            draw_O(cx, cy)
        else:
            draw_X(cx, cy)
        # set cell is filled
        m[row][col] = player
        # now you need to check whether current player wins
        ...
        # if no one wins, toggle player
        player = 2 if player == 1 else 1

def draw_O(x, y):
    radius = SIZE // 3
    w.create_oval(x-radius, y-radius, x+radius, y+radius, width=5, tag='cell')  # tag is used for resetting the game

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

Если вы хотите сбросить game:

def reset_game():
    global m
    global player
    # remove all 'O' and 'X'
    w.delete('cell')
    m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    player = 1

Для лучшего дизайна поместите все вышеперечисленные логи c в класс (унаследованный от Canvas). Тогда вы можете использовать переменные экземпляра вместо глобальных переменных.

0 голосов
/ 10 января 2020

Чтобы добавить больше подробностей к ответу tobias_k, приведенный ниже код нарисует X при нажатии правой кнопки мыши и O при нажатии левой кнопки мыши.

Улучшение кода может заключаться в используйте переменную для определения размера холста и каждого X / O вместо жесткого кодирования 200 или 300.

from tkinter import *

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]]

def drawx(event):
    print("drawx")
    x, y = event.x, event.y
    x0 = x // 300 * 300 + 50
    y0 = y // 300 * 300 + 50
    x1 = x0 + 200
    y1 = y0 + 200
    #return w.create_oval(x0, y0, x1, y1)
    w.create_line(x0,y0,x1,y1, fill = "black")
    w.create_line(x0,y0+200,x1,y1-200, fill = "black")

def drawo(event):
    print("drawo")
    x, y = event.x, event.y
    x0 = x // 300 * 300 + 50
    y0 = y // 300 * 300 + 50
    x1 = x0 + 200
    y1 = y0 + 200
    return w.create_oval(x0, y0, x1, y1)

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

w.bind('<Button-1>',drawo)
w.bind('<Button-3>',drawx)

ttt.mainloop()
...