移动椭圆形的棋盘代码

Wil*_*ong 4 python tk-toolkit tkinter python-2.7

我正在为大学做一个python跳棋游戏.我使用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
Run Code Online (Sandbox Code Playgroud)

Bry*_*ley 29

您可以使用坐标和/或移动方法在画布上移动项目,以将坐标从它们更改为您想要的坐标.

这是一个简单的示例,展示如何在画布上创建和移动项目:

import tkinter as tk     # python 3
# import Tkinter as tk   # python 2

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()
Run Code Online (Sandbox Code Playgroud)

  • 我知道这已经是过去的事了,但万一您仍在使用这种风格,我想提一下,我认为“On...”函数名称不好。首先,它们是有上限的,所以大多数人会立即认为类,你打破了传统,如果你问我有助于更快地理解。我明白你为什么想这样做,但最大的问题是你在重复自己。tag_bind 函数告诉您所有这些信息,最好解释一下该函数正在做什么,它封装了什么,而不是调用它的内容,因为这些信息可能会发生变化。 (2认同)

smc*_*mci 2

第六次编辑:这里有两个解决方案供您使用:

  1. (正如布莱恩建议的那样)要么记住移动块的旧位置,取消在那里绘制它(=>以背景颜色绘制它),然后在新位置重新绘制它
  2. 更简单:清除并重新绘制整个板

第五次编辑:好的,谢谢您删除代码。

准确解释一下您的绘图代码有什么问题?“移动的片段没有从旧位置删除”?“所有的作品都绘制在错误的坐标或颜色上”?...? 仅仅不断地转储代码并说“此代码不起作用”是不可接受的。

“我不知道如何在不删除其他部分的情况下重新绘制这些部分。” 我认为这就是你的问题所在。如果你声明并调用redrawBoard(),它应该重画所有的棋子(!),而不仅仅是移动的棋子。同意?即您必须迭代所有 board[][] 并在每块上调用 drawPiece() 。但你的代码似乎已经做到了这一点?

让我建议您如何清理现有的绘图代码,在这个过程中您几乎肯定会发现错误。显然,每次有移动(或升级)时,您都需要清除并重绘屏幕,您真的这样做了吗?redrawBoard()为此声明一个 fn 。如果不进行清除,则移动后该棋子将显示在其旧位置和新位置,这显然是错误的?(关于帧速率的评论是画布每秒更新的频率。让我想知道当您重绘时,您不需要每秒重绘 10 次,除非您还有时钟或其他变化的数据。但是,嘿,那个也有效。)

首先,强烈建议您使用枚举来自行记录board[][] 中使用的值

class Checkers():
    EMPTY=0
    RED_PIECE=1
    RED_KING=2
    BLACK_PIECE=3
    BLACK_KING=4
Run Code Online (Sandbox Code Playgroud)

接下来,您可以极大地清理画板代码。由于所有 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))
Run Code Online (Sandbox Code Playgroud)

现在,严格调用这些的板绘图代码实际上只有两种情况:(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')
Run Code Online (Sandbox Code Playgroud)

这种分解不是更容易阅读和调试吗?它是自我记录的。现在你的 bug 应该会突然出现在你面前了。

(顺便说一句,您目前绘制的国王与棋子完全相同,但我想您稍后会解决这个问题。)


第四次编辑:你让我们看到了错误的 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
Run Code Online (Sandbox Code Playgroud)