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

为何同类型棋子绘制位置重合?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)

优化说明

  1. 先按阵营和类型筛选出对应棋子列表,再给列表中的每个棋子分配唯一坐标
  2. 兵的分配直接利用枚举索引,对应棋盘的0-7列,简洁高效
  3. 每个棋子只会被设置一次位置,避免了重复赋值导致的位置覆盖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 10:10:22