移动椭圆形的棋盘代码

时间:2011-07-19 00:00:49

标签: python tkinter tk 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

2 个答案:

答案 0 :(得分:26)

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

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

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

答案 1 :(得分:2)

第6编辑:以下是两种解决方案:

  1. (正如布莱恩建议的那样)要么记住被移动的棋子的旧位置,要么将其展开(=>以背景颜色绘制),在新位置重绘
  2. 更简单:清除并重绘整个主板
  3. 第5编辑:好的,谢谢你删除了代码。

    解释完全您的电路板绘图代码有什么问题? '已移动的部分未从旧位置删除'? '所有棋子都是用错误的坐标或颜色绘制的'? ...?的 仅保留转储代码并说“此代码不起作用”是不可接受的。

      

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

    让我建议您如何清理现有的电路板绘图代码,在这个过程中,您几乎肯定会发现您的错误。 显然,每当有移动(或促销)时你需要清除并重绘屏幕,你真的这样做了吗?为此声明fn redrawBoard()。如果你不清楚,那么在移动后,这件作品将显示在旧的和新的位置,这显然是错的? (关于帧率的评论是每秒更新画布的频率。让我想知道你什么时候重绘,你不需要每秒重绘10次,除非你还有一个时钟或其他改变但是,嘿,这也有效。)

    首先,强烈建议你在[] []

    中使用use an enum to self-document the values
    class Checkers():
        EMPTY=0
        RED_PIECE=1
        RED_KING=2
        BLACK_PIECE=3
        BLACK_KING=4
    

    接下来,您可以大大清理电路板绘图代码。 由于所有4个绘图案例都称为常见案例,因此请将其设为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)假设你得到了枚举权:

    顺便说一句,永远不要使用一个更易读的for-loop可以做的while循环:

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

    这种分解是不是更容易阅读和调试?它是自我记录的。现在你的bug几乎应该向你跳出来。

    (顺便说一句,你现在正在绘制与棋子完全相同的国王,但我想你以后会解决这个问题。)


    第4编辑:你让我们看错了fns,grr ......你说你的错误实际上在电路板绘图代码中。您能否更正仍然显示“实施运动功能”的标题?


    原始回复: 什么机器向往说,这不是一个问题 - 还没有:告诉我们你目前正在尝试什么,以及为什么它不起作用。另外,删除所有不相关的代码。

    看起来你在功能moveTo(i,j)方面遇到了困难 - 但究竟是什么? (全局变量secondPass,secondPosition信号你可能遇到麻烦......你知道递归吗?如果没有,不用担心。)

    另外,作为一种风格的东西,并且为了让你的生活变得轻松,这个实现不是OO,全局性的尖叫不好分解。尝试重写为类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