为何同类型棋子绘制位置重合?Pygame国际象棋代码求助
问题定位与解决:国际象棋棋子位置重叠
问题描述
尝试为棋局中所有棋子创建对象并分配棋盘坐标,但运行代码时,同类型棋子全部绘制在同一位置。以下是相关代码:
棋子创建与位置分配代码
# piece sprites Pieces = pg.sprite.Group() WKing = piece("W", "King") WQueen = piece("W", "Queen") BKing = piece("B", "King") BQueen = piece("B", "Queen") Pieces.add(WKing, WQueen, BKing, BQueen) for j in range(2): WBishop = piece("W", "Bishop") WKnight = piece("W", "Knight") WRook = piece("W", "Rook") BBishop = piece("B", "Bishop") BKnight = piece("B", "Knight") BRook = piece("B", "Rook") Pieces.add(WBishop, WKnight, WRook, BBishop, BKnight, BRook) for i in range(8): WPawn = piece("W", "Pawn") BPawn = piece("B", "Pawn") Pieces.add(WPawn, BPawn) # set starting position of all pieces A, B, C, D, E, F, G, H = 0, 1, 2, 3, 4, 5, 6, 7 for p in Pieces: side = p.get_side() # Bishops if p.get_name() == "Bishop": for Bi in range(1, 3): if side == "W": sx, sy = p.set_position(((Bi*3)-1), 1) position = sx, sy elif side == "B": sx, sy = p.set_position(((Bi*3)-1), 8) position = sx, sy # Knights elif p.get_name() == "Knight": for Kn in range(1, 3): if side == "W": sx, sy = p.set_position((((Kn*5)-3)-1), 1) position = sx, sy elif side == "B": sx, sy = p.set_position((((Kn*5)-3)-1), 8) position = sx, sy # Rooks elif p.get_name() == "Rook": for Ro in range(1, 3): if side == "W": sx, sy = p.set_position((((Ro*7)-6)-1), 1) position = sx, sy elif side == "B": sx, sy = p.set_position((((Ro*7)-6)-1), 8) position = sx, sy # Pawns elif p.get_name() == "Pawn": for Pa in range(1, 8, 1): if side == "W": sx, sy = p.set_position(Pa, 2) position = sx, sy elif side == "B": sx, sy = p.set_position(Pa, 7) position = sx, sy # Kings elif p.get_name() == "King": if side == "W": sx, sy = p.set_position(E, 1) position = sx, sy elif side == "B": sx, sy = p.set_position(E, 8) position = sx, sy # Queens elif p.get_name() == "Queen": if side == "W": sx, sy = p.set_position(D, 1) position = sx, sy elif side == "B": sx, sy = p.set_position(D, 8) position = sx, sy
Piece类实现
class piece(pg.sprite.Sprite): def __init__(self, side, piece_name): super().__init__() self.side = side self.name = piece_name icon = "images/" + self.side + "/" + self.name + ".png" self.image = pg.image.load(icon) def set_position(self, x, y): tile_size = 40 ex, ey = (tile_size*(x))+8, (tile_size*((9-y)-1))+8 self.rect = self.image.get_rect(topleft = (ex, ey)) return (ex, ey) def get_name(self): return self.name def get_side(self): return self.side
问题原因
核心问题出在位置分配的循环逻辑:
- 遍历每个棋子时,对同类型棋子(比如所有白主教)都执行了内部的
for循环(如Bi in range(1,3)) - 这会导致单个棋子的位置被连续设置多次,最终停在循环最后一次的坐标上
- 比如两个白主教,第一个会被先设置到
Bi=1的位置,接着又被覆盖为Bi=2的位置;第二个白主教同样经历两次赋值,最终也停在Bi=2的位置,导致所有同类型棋子位置完全重叠
解决方案
去掉每个类型内部的循环,改为按类型筛选棋子后逐个分配位置,确保每个棋子只被设置一次坐标:
# 设置起始位置 A, B, C, D, E, F, G, H = 0, 1, 2, 3, 4, 5, 6, 7 # 处理王 for p in Pieces: if p.get_name() == "King": p.set_position(E, 1) if p.get_side() == "W" else p.set_position(E, 8) # 处理后 for p in Pieces: if p.get_name() == "Queen": p.set_position(D, 1) if p.get_side() == "W" else p.set_position(D, 8) # 处理车 white_rooks = [p for p in Pieces if p.get_side() == "W" and p.get_name() == "Rook"] white_rooks[0].set_position(A, 1) white_rooks[1].set_position(H, 1) black_rooks = [p for p in Pieces if p.get_side() == "B" and p.get_name() == "Rook"] black_rooks[0].set_position(A, 8) black_rooks[1].set_position(H, 8) # 处理马 white_knights = [p for p in Pieces if p.get_side() == "W" and p.get_name() == "Knight"] white_knights[0].set_position(B, 1) white_knights[1].set_position(G, 1) black_knights = [p for p in Pieces if p.get_side() == "B" and p.get_name() == "Knight"] black_knights[0].set_position(B, 8) black_knights[1].set_position(G, 8) # 处理象 white_bishops = [p for p in Pieces if p.get_side() == "W" and p.get_name() == "Bishop"] white_bishops[0].set_position(C, 1) white_bishops[1].set_position(F, 1) black_bishops = [p for p in Pieces if p.get_side() == "B" and p.get_name() == "Bishop"] black_bishops[0].set_position(C, 8) black_bishops[1].set_position(F, 8) # 处理兵 white_pawns = [p for p in Pieces if p.get_side() == "W" and p.get_name() == "Pawn"] for idx, pawn in enumerate(white_pawns): pawn.set_position(idx, 2) black_pawns = [p for p in Pieces if p.get_side() == "B" and p.get_name() == "Pawn"] for idx, pawn in enumerate(black_pawns): pawn.set_position(idx, 7)
优化说明
- 先按阵营和类型筛选出对应棋子列表,再给列表中的每个棋子分配唯一坐标
- 兵的分配直接利用枚举索引,对应棋盘的0-7列,简洁高效
- 每个棋子只会被设置一次位置,避免了重复赋值导致的位置覆盖
内容的提问来源于stack exchange,提问作者shayafreedman
相关产品推荐
相关产品推荐

