绘制代码来移动椭圆
我正在为一所大学的Python跳棋游戏工作。 我使用tk绘制了棋盘,但似乎无法实现棋子的移动function。 如果有人在我的代码中看到任何错误,或者可以提供帮助,我将不胜感激。 这是完整的来源。 提前致谢。
我知道这会吸引棋子。 我不知道如何重绘这些作品,而不删除其他作品。 我在网上查看移动function,并尝试了简单的testing工作,但我还没有能够在我的代码中使用它。
我知道recursion,但是,我需要基本的function来工作,即实际上移动一块在屏幕上,然后再执行其他function。
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
您可以使用坐标和/或移动方法在canvas上移动项目,以将坐标从原来的位置改变为您希望的位置。
下面是一个简单的例子,展示了如何在canvas上创build和移动项目:
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()
第六编辑:这里有两个解决scheme给你:
- (正如Bryan所build议的那样)要么记住被移动的棋子的旧位置,在那里将其取消(=>以背景颜色绘制),在新的位置重新绘制
- 更简单:清除并重绘整个板子
第五编辑:好的感谢剥离代码。
解释你的电路板绘图代码到底是什么问题? “移动的部分不会从旧位置删除”? “所有的作品都是以错误的坐标或颜色绘制的”? …? 只是继续倾销代码,并说“这段代码不起作用”是不可接受的。
“我不知道如何重绘这些作品,而不删除其他作品。” 我认为那是你的问题。 如果你声明和调用
redrawBoard()
,它应该重绘所有的作品(!),而不仅仅是被移动的作品。 同意? 即你必须迭代所有board [] []并在每一块上调用drawPiece()。 但是你的代码似乎已经这样做了?
让我build议你如何清理你现有的绘图代码,在这个过程中你几乎肯定会发现你的bug。 显然你需要每次移动(或升级)时清除和重画屏幕,你真的这么做吗? redrawBoard()
声明一个fn redrawBoard()
。 如果你不清楚,那么在一个移动之后,这个作品将显示在其旧的和新的位置,这显然是错误的? (关于帧速率的评论是每秒更新一次canvas的次数,这让我想知道当你重画的时候,除非你有一个时钟或者其他数据的变化,否则你不需要重绘10次,但是,嘿,也可以)。
首先,强烈build议您使用枚举来自行logging 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')
这种分解是不是非常容易阅读和debugging? 这是自我logging。 现在你的bug几乎应该跳到你身上。
(顺便说一下,你现在正在画国王一样的片断,但我想你会稍后解决。)
第四编辑:你让我们看错了fns,grr …你说你的bug实际上是在绘图代码中 。 请您改正仍然有“实现移动function”的标题吗?
原文回应:机器的渴望说,这不是一个问题 – 还没有:告诉我们你目前的尝试,为什么它不工作。 另外,删除所有不相关的代码。
看起来你有functionmoveTo(i,j)
有困难 – 但究竟是什么? (全局secondPass,secondPosition信号你可能会遇到麻烦…你知道recursion吗?如果不是,不用担心。)
另外,作为一个风格的东西,为了让你的生活变得轻松,这个实现不是面向对象,全局的尖叫坏分解。 尝试重写为类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