Чертежный код для перемещения овала

Я работаю над игрой в шашки для колледжа. Я нарисовал доску, используя tk, но я не могу реализовать функцию перемещения для фигур. Если кто-нибудь увидит какие-либо ошибки в моем коде или может предложить помощь, я был бы признателен. Вот полный источник. Заранее спасибо.

Я знаю, что это рисует кусочки шашки. Я не знаю, как перерисовать части, не удаляя другие части. Я посмотрел в Интернете на функцию перемещения и попробовал простой тест, который работал, но я не смог использовать его в своем коде.

Я знаю, что такое рекурсия, но мне нужна базовая функция для работы, то есть перемещение части на экране, прежде чем я реализую какие-либо дополнительные функции.

lst2 = []

#counter variable
i=0

#board variable is what stores the X/O/- values.
# It's a 2D list. We iterate over it, looking to see
# if there is a value that is X or O. If so, we draw
# text to the screen in the appropriate spot (based on
# i and j.
while i < len(board):
  j=0
  while j < len(board[i]):

    if board[i][j] == 2:
      lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
        (j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
        (j+1)*width + width/2 - 15, fill="Red",outline='Black'))
    elif board[i][j] == 4:
      lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
        (j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
        (j+1)*width + width/2 - 15, fill="Red",outline='Black'))
    elif board[i][j] == 1:
      lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
        (j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
        (j+1)*width + width/2 - 15, fill="Black",outline='Black'))
    elif board[i][j] == 3:
      lst2.append(canvas.create_oval((i+1)*width + width/2 + 15,
        (j+1)*height + height/2 +15,(i+1)*width + width/2 - 15,
        (j+1)*width + width/2 - 15, fill="Black",outline='Black'))

    j+=1

  i+=1

2 ответа

Вы можете переместить элемент на холсте, используя координаты и / или методы перемещения, чтобы изменить координаты с того, чем они являются, на то, что вы хотите, чтобы они были.

Вот простой пример, показывающий, как создать и переместить элемент на холсте:

import Tkinter as tk

class Example(tk.Frame):
    '''Illustrate how to drag items on a Tkinter canvas'''

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        # create a canvas
        self.canvas = tk.Canvas(width=400, height=400)
        self.canvas.pack(fill="both", expand=True)

        # this data is used to keep track of an 
        # item being dragged
        self._drag_data = {"x": 0, "y": 0, "item": None}

        # create a couple of movable objects
        self._create_token((100, 100), "white")
        self._create_token((200, 100), "black")

        # add bindings for clicking, dragging and releasing over
        # any object with the "token" tag
        self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
        self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
        self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)

    def _create_token(self, coord, color):
        '''Create a token at the given coordinate in the given color'''
        (x,y) = coord
        self.canvas.create_oval(x-25, y-25, x+25, y+25, 
                                outline=color, fill=color, tags="token")

    def on_token_press(self, event):
        '''Begining drag of an object'''
        # record the item and its location
        self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
        self._drag_data["x"] = event.x
        self._drag_data["y"] = event.y

    def on_token_release(self, event):
        '''End drag of an object'''
        # reset the drag information
        self._drag_data["item"] = None
        self._drag_data["x"] = 0
        self._drag_data["y"] = 0

    def on_token_motion(self, event):
        '''Handle dragging of an object'''
        # compute how much the mouse has moved
        delta_x = event.x - self._drag_data["x"]
        delta_y = event.y - self._drag_data["y"]
        # move the object the appropriate amount
        self.canvas.move(self._drag_data["item"], delta_x, delta_y)
        # record the new position
        self._drag_data["x"] = event.x
        self._drag_data["y"] = event.y

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

6-е ИЗДАНИЕ: вот два решения для вас:

  1. (как предлагает Брайан) либо запомните старое местоположение перемещенного фрагмента, перерисовайте его там (=> нарисуйте его в цвете фона), перерисуйте его на новом месте
  2. проще: очистить и перерисовать всю доску

5-е РЕДАКТИРОВАНИЕ: Хорошо, спасибо за удаление кода.

Объясните точно, в чем проблема с вашим кодом для рисования на доске? "Перемещенный фрагмент не удален из старого местоположения"? "Все части нарисованы с неправильными координатами или цветами"? ...? Недопустимо просто сохранять дамп кода и говорить: "Этот код не работает".

"Я не знаю, как перерисовать части, не удаляя другие части". Я думаю, что это ваша проблема прямо здесь. Если вы объявите и позвоните redrawBoard(), он должен перерисовать ВСЕ части (!), а не только перемещенную часть. Согласен? то есть вы должны перебирать всю доску [][] и вызывать drawPiece() для каждой фигуры. Но ваш код, кажется, уже делает это?

Позвольте мне предложить вам, как очистить существующий код рисования доски, и в этом процессе вы почти наверняка найдете свою ошибку. Очевидно, что вам нужно очищать и перерисовывать экран каждый раз, когда происходит какое-либо движение (или продвижение), вы на самом деле это делаете? Объявить redrawBoard() для этого. Если вы не сделаете очистку, то после хода фигура будет отображаться в ее старых И новых местах, что, очевидно, было бы неправильно? (Комментарий о частоте кадров - это то, как часто холст будет обновляться каждую секунду. Меня удивляет, когда вы перерисовываете, вам не нужно перерисовывать 10 раз в секунду, если у вас также нет часов или других изменяющихся данных. Но, эй, это тоже работает.)

Во-первых, настоятельно рекомендуем использовать enum для самостоятельного документирования значений, используемых в board[][]

class Checkers():
    EMPTY=0
    RED_PIECE=1
    RED_KING=2
    BLACK_PIECE=3
    BLACK_KING=4

Далее вы можете значительно убрать код рисования доски. Так как все 4 случая рисования фрагментов вызывают общий случай, сделайте его fn, и сделайте этот fn незагроможденным:

def drawPiece(i,j,fillColor,outlineColor):
    """Draw single piece on screen."""
    x = (i+1)*width + width/2
    y = (j+1)*height + height/2
    lst2.append(canvas.create_oval(x+15,y+15,x-15,y-15,fill=fillColor,outline=outlineColor))

Теперь код рисования доски, который вызывает их строго, имеет только два случая: (2,4) или (1,3), если вы правильно выполнили перечисление:

и, между прочим, никогда не используйте цикл while, когда более понятный цикл for:

for i in range(len(board)):
    for j in range(len(board[i])):
        if board[i][j] in (RED_PIECE,RED_KING):
            drawPiece(i,j,'Red','Black')
        elif board[i][j] in (BLACK_PIECE,BLACK_KING):
            drawPiece(i,j,'Black','Black')

Разве это не бесконечно легче читать и отлаживать? Это самодокументирование. Теперь ваша ошибка должна практически выпрыгнуть на вас.

(Кстати, вы сейчас рисуете королей точно так же, как фигуры, но я думаю, вы исправите это позже.)


4-е РЕДАКТИРОВАНИЕ: Вы заставили нас смотреть неправильные fns, grr... вы говорите, что ваша ошибка на самом деле в коде рисования доски. Не могли бы вы исправить заголовок, который по-прежнему гласит "Реализация функции движения"?


ОРИГИНАЛЬНЫЙ ОТВЕТ: О том, что жаждет машина, это не вопрос - пока нет: расскажите нам, что вы сейчас пробуете, и почему это не работает. Также удалите весь несвязанный код.

Похоже, у вас проблемы с функцией moveTo(i,j) - а что именно? (Глобал secondPass, secondPosition сигнализируют, что у вас могут быть проблемы... знаете ли вы рекурсию? Если нет, то не беспокойтесь.)

Кроме того, как стилистическая вещь, и чтобы сделать вашу жизнь проще, эта реализация не является ОО, глобальные крики кричат ​​о плохой декомпозиции. Попробуйте переписать как класс Checkers, сделайте правление и т.д. членом, напишите init() метод. Я бы переименовал функцию grid(x,y) в initialize(nrows,ncols),

(И кашель, кашель! Признаки того, что вы адаптировали это от кого-то другого...)

#Frame rate is how often canvas will be updated
# each second. For Tic Tac Toe, 10 should be plenty.
FRAME_RATE = 10
Другие вопросы по тегам