You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 22:24:05