[英]Move and update chess piece on chessboard without clicks Tkinter Python
我正在嘗試為 Knight's Tour 問題制作一個 GUI。 我已經以排序字典的形式解決了這個問題。 現在我只希望騎士的棋子遵循保存的字典顯示的路徑並在 GUI 中跟蹤它。 除了運行腳本之外,不需要用戶輸入。
# a solution to the Knight's Tour problem with initial position (7,7) stored in a dictionary
# with keys as the order of points to visit and values as the coordinates of the points.
board_path_dict = {0: [(7, 7)], 1: [(6, 5)], 2: [(5, 7)], 3: [(7, 6)], 4: [(6, 4)], 5: [(7, 2)], 6: [(6, 0)],
7: [(4, 1)], 8: [(2, 0)], 9: [(0, 1)], 10: [(1, 3)], 11: [(0, 5)], 12: [(1, 7)], 13: [(3, 6)], 14: [(1, 5)],
15: [(0, 7)], 16: [(2, 6)], 17: [(4, 7)], 18: [(6, 6)], 19: [(7, 4)], 20: [(6, 2)], 21: [(7, 0)],
22: [(5, 1)], 23: [(3, 0)], 24: [(1, 1)], 25: [(0, 3)], 26: [(2, 2)], 27: [(1, 0)], 28: [(0, 2)],
29: [(1, 4)], 30: [(0, 6)], 31: [(2, 7)], 32: [(4, 6)], 33: [(6, 7)], 34: [(7, 5)], 35: [(5, 6)],
36: [(3, 7)], 37: [(4, 5)], 38: [(5, 3)], 39: [(3, 4)], 40: [(5, 5)], 41: [(6, 3)], 42: [(7, 1)],
43: [(5, 0)], 44: [(4, 2)], 45: [(6, 1)], 46: [(7, 3)], 47: [(5, 4)], 48: [(3, 5)], 49: [(4, 3)],
50: [(3, 1)], 51: [(2, 3)], 52: [(4, 4)], 53: [(5, 2)], 54: [(4, 0)], 55: [(3, 2)], 56: [(2, 4)],
57: [(1, 6)], 58: [(0, 4)], 59: [(2, 5)], 60: [(3, 3)], 61: [(2, 1)], 62: [(0, 0)], 63: [(1, 2)]}
我還有一個使用Tkinter為 GUI 實現的基本代碼。
import tkinter as tk
class GameBoard(tk.Frame):
def __init__(self, parent, rows=8, columns=8, size=64, color1="#a7ab90", color2="#0e140c"):
'''size is the size of a square, in pixels'''
self.rows = rows
self.columns = columns
self.size = size
self.color1 = color1
self.color2 = color2
self.pieces = {}
canvas_width = columns * size
canvas_height = rows * size
tk.Frame.__init__(self, parent)
self.canvas = tk.Canvas(self, borderwidth=0, highlightthickness=0,
width=canvas_width, height=canvas_height, background="khaki")
self.canvas.pack(side="top", fill="both", expand=True, padx=2, pady=2)
# this binding will cause a refresh if the user interactively
# changes the window size
self.canvas.bind("<Configure>", self.refresh)
def addpiece(self, name, image, row=0, column=0):
'''Add a piece to the playing board'''
self.canvas.create_image(0,0, image=image, tags=(name, "piece"), anchor="c")
self.placepiece(name, row, column)
def placepiece(self, name, row, column):
'''Place a piece at the given row/column'''
self.pieces[name] = (row, column)
x0 = (column * self.size) + int(self.size/2)
y0 = (row * self.size) + int(self.size/2)
self.canvas.coords(name, x0, y0)
def refresh(self, event):
'''Redraw the board, possibly in response to window being resized'''
xsize = int((event.width-1) / self.columns)
ysize = int((event.height-1) / self.rows)
self.size = min(xsize, ysize)
self.canvas.delete("square")
color = self.color2
for row in range(self.rows):
color = self.color1 if color == self.color2 else self.color2
for col in range(self.columns):
x1 = (col * self.size)
y1 = (row * self.size)
x2 = x1 + self.size
y2 = y1 + self.size
self.canvas.create_rectangle(x1, y1, x2, y2, outline="black", fill=color, tags="square")
color = self.color1 if color == self.color2 else self.color2
for name in self.pieces:
self.placepiece(name, self.pieces[name][0], self.pieces[name][1])
self.canvas.tag_raise("piece")
self.canvas.tag_lower("square")
if __name__ == "__main__":
root = tk.Tk()
root.title("Knight's Tour Problem")
board = GameBoard(root)
board.pack(side="top", fill="both", expand="true", padx=10, pady=10)
# knight = tk.PhotoImage(file = r"C:\Gfg\knight.png")
knight = tk.PhotoImage(file = "chess_knight.png")
board.addpiece("knight", knight, 7,7) # initial position of Knight is (7,7) here, but I plan to change that manually as the solution changes
for i in range(len(board_path_dict)-1):
cell_1 = board_path_dict[i][0]
cell_2 = board_path_dict[i+1][0]
board.canvas.create_line(cell_1[0], cell_1[1], cell_2[0], cell_2[1], width=4.3, fill='red')
board.canvas.update()
root.mainloop()
我無法使用 for 循環更新騎士棋子的位置。 GUI 窗口中的輸出是這樣的:
我希望結果是這樣的:
有可能這樣做嗎?
蒂亞!
您可以使用board.placepiece()
移動棋子。 此外,最好在 tkinter 應用程序中使用.after()
而不是 for 循環。
首先在GameBoard
類中添加一個函數來在單元格之間畫一條線:
class GameBoard(tk.Frame):
...
def draw_line(self, x1, y1, x2, y2, width, fill):
x1 *= self.size
y1 *= self.size
x2 *= self.size
y2 *= self.size
half = self.size / 2
self.canvas.create_line(x1+half, y1+half, x2+half, y2+half, width=width, fill=fill)
然后使用.after()
重復調用函數而不是 for 循環:
if __name__ == '__main__':
...
board.addpiece("knight", knight, 7,7) # initial position of Knight is (7,7) here, but I plan to change that manually as the solution changes
def move_piece(i=0):
if i < len(board_path_dict)-1:
cell_1 = board_path_dict[i][0]
cell_2 = board_path_dict[i+1][0]
# draw the line
board.draw_line(cell_1[0], cell_1[1], cell_2[0], cell_2[1], width=4.3, fill='red')
# move the chess piece
board.placepiece("knight", cell_2[1], cell_2[0])
board.after(500, move_piece, i+1)
# start the chess piece moving
board.after(500, move_piece)
root.mainloop()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.