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

Python国际象棋GUI棋子图片加载异常问题求助

国际象棋GUI棋子图片加载异常解决方案

问题概述

我用Python开发了一款可与Stockfish对弈的国际象棋程序,实现了简易GUI展示棋子。黑棋图片命名为p、r、n、b、q、k,白棋为P、R、N、B、Q、K。初始运行时棋盘两侧均加载黑棋图片,推测是Windows自动给白棋文件名添加(2)后缀导致。修改代码后却变为两侧均加载白棋图片,调整draw_board代码无效果,修改文件名则导致GUI无法启动。

问题根源

  1. 字典key覆盖问题:在load_piece_images方法中,所有棋子图片的key都被转成小写,导致白棋的大写符号(如P)加载时会覆盖黑棋小写符号(如p)的图片,最终所有棋子都调用最后加载的白棋图片。
  2. 文件名匹配逻辑缺陷:fnmatch的匹配规则没有严格区分黑白棋的大小写前缀,加上Windows自动添加的后缀,导致图片匹配混乱。

修复方案

1. 修正图片字典的key存储

不再统一将key转为小写,直接使用棋子的原始符号(区分大小写)作为key,确保黑白棋图片分别存储。

2. 优化文件名匹配规则

针对黑白棋的大小写前缀,精准匹配文件名,同时兼容Windows自动添加的(2)这类后缀。

3. 调整图片调用逻辑

在draw_board中直接使用棋子的原始symbol获取对应图片,无需转小写。

修改后的完整代码

import chess
import chess.engine
import tkinter as tk
from tkinter import simpledialog, messagebox
from PIL import Image, ImageTk
import os
import fnmatch


class ChessGUI(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("Chess Game")
        self.geometry("600x600")

        self.canvas = tk.Canvas(self, width=600, height=600, bg="white")
        self.canvas.pack(fill=tk.BOTH, expand=True)

        self.board = chess.Board()
        self.load_piece_images()

        self.draw_board()

    def load_piece_images(self):
        self.piece_images = {}
        # 黑棋用小写,白棋用大写,分别对应
        piece_symbols = ["p", "r", "n", "b", "q", "k", "P", "R", "N", "B", "Q", "K"]

        for piece_symbol in piece_symbols:
            try:
                # 匹配以目标符号开头,后面可跟任意字符(包括(2)),最后以.png结尾的文件
                # 严格区分大小写,确保黑棋匹配小写开头,白棋匹配大写开头
                files = [f for f in os.listdir("pieces") 
                         if fnmatch.fnmatch(f, f"{piece_symbol}*.png")]
                if files:
                    img_path = f"pieces/{files[0]}"
                    img = Image.open(img_path)
                    img = img.resize((75, 75), Image.BILINEAR)
                    # 直接用原始symbol作为key,不转小写
                    self.piece_images[piece_symbol] = ImageTk.PhotoImage(img)
                    print(f"Loaded image for {piece_symbol} from {img_path}")
                else:
                    print(f"No matching image found for {piece_symbol}. Skipping.")
            except Exception as e:
                print(f"Error loading image for {piece_symbol}: {str(e)}. Skipping.")

    def draw_board(self):
        self.canvas.delete("all")

        for square in chess.SQUARES:
            rank, file = chess.square_rank(square), chess.square_file(square)
            color = "white" if (rank + file) % 2 == 0 else "black"
            x, y = file * 75, (7 - rank) * 75

            self.canvas.create_rectangle(x, y, x + 75, y + 75, fill=color)

            piece = self.board.piece_at(square)
            if piece:
                print(piece.symbol())
                # 直接用棋子的原始symbol获取图片,无需转小写
                piece_image = self.piece_images[piece.symbol()]
                self.canvas.create_image(x + 37.5, y + 37.5, image=piece_image)

    def get_user_move(self):
        user_move = simpledialog.askstring("Your Move", "Enter your move (in UCI format, e.g., e2e4):")
        try:
            self.board.push_uci(user_move)
            self.draw_board()
        except ValueError:
            messagebox.showerror("Invalid Move", "Invalid move. Try again.")
            self.get_user_move()

    def get_stockfish_move(self):
        stockfish_path = "D:/Test/stockfish/stockfish.exe"  # 替换为你的Stockfish实际路径
        with chess.engine.SimpleEngine.popen_uci(stockfish_path) as engine:
            result = engine.play(self.board, chess.engine.Limit(time=2.0))
            return result.move

    def play_game(self):
        while not self.board.is_game_over():
            self.draw_board()

            if self.board.turn == chess.WHITE:
                self.get_user_move()
            else:
                stockfish_move = self.get_stockfish_move()
                self.board.push(stockfish_move)

        self.draw_board()
        messagebox.showinfo("Game Over", f"Game Over!\nResult: {self.board.result()}")

if __name__ == "__main__":
    chess_gui = ChessGUI()
    chess_gui.play_game()
    chess_gui.mainloop()

额外注意事项

  • 确保pieces文件夹下的图片文件名正确:黑棋为p.png、r.png等,白棋为P.png、R.png等,如果有(2)后缀,可手动重命名移除,或者代码中的匹配规则已经兼容这类后缀。
  • 运行前确认PIL库、python-chess库已安装,可通过pip install pillow python-chess安装。

内容的提问来源于stack exchange,提问作者Ineedhelpwithpython

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 13:20:56