Python Tkinter国际象棋游戏中如何按坐标移动或删除棋子图片
Tkinter国际象棋棋子移动残留问题解决方案
问题根因:你每次调用actu()刷新棋子时,仅在画布上新建棋子图像,从未删除旧的棋子元素,导致原位置的图像一直残留。同时原鼠标点击逻辑存在判断冗余、缺少选中状态校验的问题,容易触发未定义变量报错。
下面提供两种可直接落地的方案:
方案1:快速改造(全量刷新,改造成本极低)
适合小型项目使用,仅需要修改少量代码:
- 给所有棋子增加统一的tag标记,每次刷新前先清空所有带该tag的旧棋子
- 修复鼠标点击逻辑,增加选中状态校验和边界判断,避免点空白格/棋盘外报错
- 修正原矩阵长度不一致的问题,避免索引越界
修改后可直接运行的代码:
from tkinter import * import math root = Tk() root.title("Chess") root.geometry("500x500") frame = Frame(root) frame.pack() canvas = Canvas(frame, bg="black", width=500, height=500) canvas.pack() # 替换为你自己的棋盘背景路径 background = PhotoImage(file="image/Chessboard.png") canvas.create_image(250,250,image=background) pion = PhotoImage(file="image/W_pion.png") # 修正原矩阵长度不一致问题,统一为8*8 Matrixe= [["","","","","","","",""], ["","","","","","","",""], ["","","","","","","",""], ["","","","","","","",""], ["","","","","","","",""], ["","","","","","","",""], ["W_Pion","W_Pion","W_Pion","W_Pion","W_Pion","W_Pion","W_Pion","W_Pion"], ["","","","","","","",""]] ligne=len(Matrixe) col=len(Matrixe[0]) # 新增选中状态、选中棋子位置变量 is_selected = False preY = preX = 0 piece = "" def actu(): # 先清空所有旧棋子 canvas.delete("piece") for l in range(ligne): for c in range(col): if Matrixe[c][l] == "W_Pion": # 给棋子加统一tag方便后续批量操作 canvas.create_image(62.5 * l + 33,62.5 * c + 33,image=pion, tag="piece") actu() def getorigin(eventorigin): global is_selected, preY, preX, piece Posx = eventorigin.x Posy = eventorigin.y Xcase = math.ceil((Posx / 62)) - 1 Ycase = math.ceil((Posy / 62)) - 1 # 边界校验,点击棋盘外直接返回 if Xcase <0 or Xcase >= col or Ycase <0 or Ycase >= ligne: return # 点击有棋子的格子,执行选中 if Matrixe[Ycase][Xcase] != "": piece = Matrixe[Ycase][Xcase] preY = Ycase preX = Xcase is_selected = True # 点击空格子且已经选中棋子,执行移动 elif is_selected: Matrixe[Ycase][Xcase] = piece Matrixe[preY][preX] = "" is_selected = False actu() canvas.bind("<Button-1>", getorigin) # 没有图标可以注释掉下面这行 # root.iconbitmap("icon.ico") root.mainloop()
方案2:高效实现(单棋子操作,无需全量重绘)
如果棋子数量多、对性能有要求,可以用这个方案:
- 新增一个和棋盘矩阵同尺寸的
piece_ids矩阵,存储每个位置棋子的canvas元素ID - 移动棋子时直接调用
canvas.coords(棋子ID, 新x坐标, 新y坐标)修改位置,不需要删除重建 - 要删除指定位置棋子时,调用
canvas.delete(piece_ids[y][x])后把对应位置的ID置空即可
内容的提问来源于stack exchange,提问作者BerretMan
相关产品推荐
相关产品推荐

