Python国际象棋GUI棋子图片加载异常问题求助
国际象棋GUI棋子图片加载异常解决方案
问题概述
我用Python开发了一款可与Stockfish对弈的国际象棋程序,实现了简易GUI展示棋子。黑棋图片命名为p、r、n、b、q、k,白棋为P、R、N、B、Q、K。初始运行时棋盘两侧均加载黑棋图片,推测是Windows自动给白棋文件名添加(2)后缀导致。修改代码后却变为两侧均加载白棋图片,调整draw_board代码无效果,修改文件名则导致GUI无法启动。
问题根源
- 字典key覆盖问题:在
load_piece_images方法中,所有棋子图片的key都被转成小写,导致白棋的大写符号(如P)加载时会覆盖黑棋小写符号(如p)的图片,最终所有棋子都调用最后加载的白棋图片。 - 文件名匹配逻辑缺陷:
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
相关产品推荐
相关产品推荐

