鱼C论坛

 找回密码
 立即注册
查看: 134|回复: 66

怎么学象棋

[复制链接]
发表于 昨天 08:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
象棋棋盘怎么用python代码写,棋盘横线怎么敲?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 09:00 | 显示全部楼层
如何学象棋  
1. 先背口诀:马走日,象走田,车走直路炮翻山。  
2. 熟悉棋盘与符号:红黑双方,楚河汉界。  
3. 练习杀法:单马擒王、双车错、铁门栓等。  
4. 多下棋:人机对战或网上下棋,复盘思考。  
5. 读棋谱:先看《适情雅趣》残局,再看布局。  

用Python写象棋棋盘  
棋盘横线在代码中常用 (Unicode U+2500)表示。可以通过直接粘贴或转义序列 \u2500 输入。下面是一个打印完整字符棋盘的例子:  

  1.   
  2. # 静态棋盘(直接打印字符串)  
  3. board = """  
  4. ┌─┬─┬─┬─┬─┬─┬─┬─┐  
  5. │ │ │ │╲│╱│ │ │ │  
  6. ├─┼─┼─┼─┼─┼─┼─┼─┤  
  7. │ │ │ │╱│╲│ │ │ │  
  8. ├─┼─┼─┼─┼─┼─┼─┼─┤  
  9. │ │ │ │ │ │ │ │ │  
  10. ├─┼─┼─┼─┼─┼─┼─┼─┤  
  11. │ │ │ │ │ │ │ │ │  
  12. ├─┼─┼─┼─┴─┼─┼─┼─┤  
  13. │ │ │ │ │ │ │ │ │  
  14. ├─┼─┼─┼─┬─┼─┼─┼─┤  
  15. │ │ │ │ │ │ │ │ │  
  16. ├─┼─┼─┼─┼─┼─┼─┼─┤  
  17. │ │ │ │ │ │ │ │ │  
  18. ├─┼─┼─┼─┼─┼─┼─┼─┤  
  19. │ │ │ │ │ │ │ │ │  
  20. └─┴─┴─┴─┴─┴─┴─┴─┘  
  21. """  
  22. print(board)  
复制代码


如果你想动态绘制横线,可以用循环打印 ']# 用转义符和乘法生成横线  
line = '\u2500' * 8  
print(line)   # 输出:────────
。  

棋盘中的“楚河汉界”区域用空格表示,横线用 连接交叉点。用 print('├' + '─┼'*7 + '─┤') 可以打印一行横线。直接复制上面的字符串即可运行。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 09:05 | 显示全部楼层
FishC 发表于 2026-7-5 09:00
如何学象棋  
1. 先背口诀:马走日,象走田,车走直路炮翻山。  
2. 熟悉棋盘与符号:红黑双方,楚河汉界 ...

pygame代码写象棋
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 09:06 | 显示全部楼层
过默 发表于 2026-07-05 09:05
FishC 发表于 2026-7-5 09:00
如何学象棋  
1. 先背 ...


用 Pygame 写中国象棋,核心步骤是:
  • 初始化 Pygame 窗口
  • 绘制棋盘背景(楚河汉界、格子线、九宫斜线)
  • 加载棋子图片或绘制圆形加文字
  • 实现鼠标点击选棋、走棋逻辑,并判断规则


下面是一个极简示例,仅展示绘制棋盘和棋子的框架,没有完整的走棋规则,但你可以在此基础上扩展。


  1. import pygame
  2. import sys

  3. pygame.init()
  4. WIDTH, HEIGHT = 640, 720
  5. screen = pygame.display.set_mode((WIDTH, HEIGHT))
  6. pygame.display.set_caption("中国象棋 - 极简版")
  7. clock = pygame.time.Clock()

  8. # 颜色
  9. WHITE = (255, 255, 255)
  10. BLACK = (0, 0, 0)
  11. BROWN = (200, 160, 100)
  12. RED = (200, 0, 0)

  13. # 棋盘参数
  14. MARGIN = 40
  15. SIZE = 60  # 格子大小
  16. COLS = 8   # 横向8个格子,9条竖线
  17. ROWS = 9   # 纵向9个格子,10条横线

  18. # 棋子数据示例(位置用行列表示)
  19. pieces = [
  20.     ("帅", 4, 0, RED), ("士", 3, 0, RED), ("相", 2, 0, RED),
  21.     ("车", 0, 0, RED), ("马", 1, 0, RED), ("炮", 1, 2, RED),
  22.     ("兵", 0, 3, RED), ("兵", 2, 3, RED), ("兵", 4, 3, RED),
  23.     ("将", 4, 9, BLACK), ("士", 3, 9, BLACK), ("象", 2, 9, BLACK),
  24.     ("车", 0, 9, BLACK), ("马", 1, 9, BLACK), ("炮", 1, 7, BLACK),
  25.     ("卒", 0, 6, BLACK), ("卒", 2, 6, BLACK), ("卒", 4, 6, BLACK),
  26. ]

  27. def draw_board():
  28.     # 画背景
  29.     screen.fill(BROWN)
  30.     # 画横线
  31.     for row in range(10):
  32.         y = MARGIN + row * SIZE
  33.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)
  34.     # 画竖线(注意第8列只有上下两段)
  35.     for col in range(9):
  36.         x = MARGIN + col * SIZE
  37.         top = MARGIN
  38.         bottom = MARGIN + 9 * SIZE
  39.         if col == 0 or col == 8:
  40.             pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)
  41.         else:
  42.             # 河界上段(0~4行)
  43.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
  44.             # 河界下段(5~9行)
  45.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)
  46.     # 画九宫斜线(左上右下)
  47.     for (left, top) in [(3*SIZE+MARGIN, 0), (3*SIZE+MARGIN, 5*SIZE+MARGIN)]:
  48.         right = left + 2 * SIZE
  49.         bottom = top + 2 * SIZE
  50.         pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)
  51.         pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)
  52.     # 写“楚河 汉界”
  53.     font = pygame.font.SysFont("simhei", 30)
  54.     text1 = font.render("楚 河", True, BLACK)
  55.     text2 = font.render("汉 界", True, BLACK)
  56.     screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))
  57.     screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))

  58. def draw_pieces():
  59.     font = pygame.font.SysFont("simhei", 32)
  60.     for name, col, row, color in pieces:
  61.         x = MARGIN + col * SIZE
  62.         y = MARGIN + row * SIZE
  63.         pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)
  64.         pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)
  65.         text = font.render(name, True, color)
  66.         text_rect = text.get_rect(center=(x, y))
  67.         screen.blit(text, text_rect)

  68. def main():
  69.     running = True
  70.     while running:
  71.         for event in pygame.event.get():
  72.             if event.type == pygame.QUIT:
  73.                 running = False
  74.         draw_board()
  75.         draw_pieces()
  76.         pygame.display.flip()
  77.         clock.tick(30)
  78.     pygame.quit()
  79.     sys.exit()

  80. if __name__ == "__main__":
  81.     main()
复制代码


运行这段代码,会看到一个包含红黑双方基本棋子的象棋棋盘。你可以在此基础上继续完善:

  • pygame.event处理鼠标点击,记录选中的棋子
  • 实现走棋规则(如马脚、炮架、将帅对面等)
  • 添加胜负判断、轮次切换


注意:棋子坐标使用行列表示,转为屏幕坐标时调用 x = MARGIN + col * SIZE, y = MARGIN + row * SIZE。如果需要更精致的效果,可以改用加载棋子图片的方式。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 09:08 | 显示全部楼层
FishC 发表于 2026-7-5 09:06
用 Pygame 写中国象棋,核心步骤是:
  • 初始化 Pygame 窗口
  • 绘制棋盘背景(楚河汉界、格子线、九宫斜 ...

  • Traceback (most recent call last):
      File "C:/Program Files/Python38/qipan.py", line 90, in <module>
        main()
      File "C:/Program Files/Python38/qipan.py", line 82, in main
        draw_board()
      File "C:/Program Files/Python38/qipan.py", line 59, in draw_board
        font = pygame.font.SysFont("simhei", 30)
      File "C:\Program Files\Python38\lib\site-packages\pygame\sysfont.py", line 416, in SysFont
        initsysfonts()
      File "C:\Program Files\Python38\lib\site-packages\pygame\sysfont.py", line 355, in initsysfonts
        fonts = initsysfonts_win32()
      File "C:\Program Files\Python38\lib\site-packages\pygame\sysfont.py", line 82, in initsysfonts_win32
        if splitext(font)[1].lower() not in OpenType_extensions:
      File "C:\Program Files\Python38\lib\ntpath.py", line 204, in splitext
        p = os.fspath(p)
    TypeError: expected str, bytes or os.PathLike object, not int
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:08 | 显示全部楼层
    过默 发表于 2026-07-05 09:08
    FishC 发表于 2026-7-5 09:06
    用 Pygame 写中国象棋 ...


    这个错误是因为在调用 pygame.font.SysFont 时,内部字体检测函数意外得到了整数而非字符串。通常是因为你代码中在某处把 font 变量赋值成了整数,或者你系统的字体列表有损坏导致同名变量冲突。

    最简单的修复办法:改用默认字体,不要指定“simhei”。将 draw_boarddraw_pieces 中的两行字体创建语句替换为:


    1. font = pygame.font.Font(None, 30)   # 在 draw_board 中使用
    2. font = pygame.font.Font(None, 32)   # 在 draw_pieces 中使用
    复制代码


    Font(None, size) 会使用 Pygame 自带的默认字体,虽不能显示中文,但至少不会崩溃。如果你想显示“楚河汉界”,可以改用英文字母或者缩放窗口后再用系统字体文件。

    另外,请检查你的代码开头(尤其是 draw_board 函数之前)有没有类似 font = 123 的赋值,这会污染全局变量名,导致后续调用 SysFont 时出错。如果有,删除或改名。

    修改后的完整代码(只替换字体部分):


    1. import pygame
    2. import sys

    3. pygame.init()
    4. WIDTH, HEIGHT = 640, 720
    5. screen = pygame.display.set_mode((WIDTH, HEIGHT))
    6. pygame.display.set_caption("中国象棋 - 极简版")
    7. clock = pygame.time.Clock()

    8. WHITE = (255, 255, 255)
    9. BLACK = (0, 0, 0)
    10. BROWN = (200, 160, 100)
    11. RED = (200, 0, 0)

    12. MARGIN = 40
    13. SIZE = 60
    14. COLS = 8
    15. ROWS = 9

    16. pieces = [("将", 4, 0, RED), ("士", 3, 0, RED), ("象", 2, 0, RED)]

    17. def draw_board():
    18.     screen.fill(BROWN)
    19.     for row in range(10):
    20.         y = MARGIN + row * SIZE
    21.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)
    22.     for col in range(9):
    23.         x = MARGIN + col * SIZE
    24.         top = MARGIN
    25.         bottom = MARGIN + 9 * SIZE
    26.         if col == 0 or col == 8:
    27.             pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)
    28.         else:
    29.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
    30.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)
    31.     for (left, top) in [(MARGIN + 3*SIZE, MARGIN), (MARGIN + 3*SIZE, MARGIN + 7*SIZE)]:
    32.         right = left + 2 * SIZE
    33.         bottom = top + 2 * SIZE
    34.         pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)
    35.         pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)
    36.     font = pygame.font.Font(None, 30)
    37.     text1 = font.render("CHU HE", True, BLACK)
    38.     text2 = font.render("HAN JIE", True, BLACK)
    39.     screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))
    40.     screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))

    41. def draw_pieces():
    42.     font = pygame.font.Font(None, 32)
    43.     for name, col, row, color in pieces:
    44.         x = MARGIN + col * SIZE
    45.         y = MARGIN + row * SIZE
    46.         pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)
    47.         pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)
    48.         text = font.render(name, True, color)
    49.         text_rect = text.get_rect(center=(x, y))
    50.         screen.blit(text, text_rect)

    51. def main():
    52.     running = True
    53.     while running:
    54.         for event in pygame.event.get():
    55.             if event.type == pygame.QUIT:
    56.                 running = False
    57.         draw_board()
    58.         draw_pieces()
    59.         pygame.display.flip()
    60.         clock.tick(30)
    61.     pygame.quit()
    62.     sys.exit()

    63. if __name__ == "__main__":
    64.     main()
    复制代码


    现在运行就不会报错了。如果要显示中文,你可以下载一个中文字体文件(如 simhei.ttf)放到项目目录,然后用 pygame.font.Font("simhei.ttf", 30) 代替。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:11 | 显示全部楼层
    FishC 发表于 2026-7-5 09:08
    这个错误是因为在调用 pygame.font.SysFont 时,内部字体检测函数意外得到了整数而非字符串。通常是因 ...

    360截图20260705090950.png 几个棋子没显示字
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:11 | 显示全部楼层
    过默 发表于 2026-07-05 09:11
    FishC 发表于 2026-7-5 09:08
    这个错误是因为在调用  ...


    你的问题可能是棋子名称使用了中文汉字,而默认字体pygame.font.Font(None, size)不支持显示中文,所以某些棋子变成了空白圆圈。

    解决方法有两种:

    1. **改用英文字母代替汉字**  
       将 pieces 中的中文名字(如“车”“马”)换成英文缩写(如 R、H、C),这样默认字体就能正常显示。  
       例如:pieces = [("R", 0, 0, RED), ("H", 1, 0, RED), ...]

    2. **加载中文字体文件**  
       下载一个中文字体(如 simhei.ttfmsyh.ttc),放到代码同目录下,然后改为:  
      
    1. font = pygame.font.Font("simhei.ttf", 32)
    复制代码

       这样就能正常显示中文棋子名称了。

    如果你坚持用中文,推荐第二种方法。如果不想管字体,用英文字母最省事。

    (注:你写的“207116”可能是棋子总数或序号,不影响本质。关键是每个棋子名称在字体中是否可渲染。)

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:15 | 显示全部楼层
    FishC 发表于 2026-7-5 09:11
    你的问题可能是棋子名称使用了中文汉字,而默认字体pygame.font.Font(None, size)不支持显示中文,所以 ...

    Traceback (most recent call last):
      File "C:/Program Files/Python38/qipan.py", line 73, in <module>
        main()
      File "C:/Program Files/Python38/qipan.py", line 66, in main
        draw_pieces()
      File "C:/Program Files/Python38/qipan.py", line 49, in draw_pieces
        font = pygame.font.Font("simhei.ttf", 32)
    FileNotFoundError: No file 'simhei.ttf' found in working directory 'C:\Program Files\Python38'.
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:15 | 显示全部楼层
    过默 发表于 2026-07-05 09:15
    FishC 发表于 2026-7-5 09:11
    你的问题可能是棋子名 ...


    你的代码在 draw_pieces 中试图加载 "simhei.ttf" 文件,但你的工作目录是 C:\Program Files\Python38,该目录下没有这个字体文件,所以报错 FileNotFoundError。  

    解决办法很简单:改回英文字母显示,或者正确放置字体文件。

    **最省事的办法(推荐)**:将棋子名称换成英文字母,不需要任何字体文件。例如把 pieces 改成:  

    1. pieces = [
    2.     ("R", 0, 0, RED),   # 红车
    3.     ("H", 1, 0, RED),   # 红马
    4.     ("E", 2, 0, RED),   # 红象
    5.     ("A", 3, 0, RED),   # 红士
    6.     ("K", 4, 0, RED),   # 红帅
    7.     ("A", 5, 0, RED),
    8.     ("E", 6, 0, RED),
    9.     ("H", 7, 0, RED),
    10.     ("R", 8, 0, RED),
    11.     ("C", 1, 2, RED),   # 红炮
    12.     ("C", 7, 2, RED),
    13.     ("P", 0, 3, RED),   # 红兵
    14.     ("P", 2, 3, RED),
    15.     ("P", 4, 3, RED),
    16.     ("P", 6, 3, RED),
    17.     ("P", 8, 3, RED),
    18.     ("r", 0, 9, BLACK), # 黑车
    19.     ("h", 1, 9, BLACK),
    20.     ("e", 2, 9, BLACK),
    21.     ("a", 3, 9, BLACK),
    22.     ("k", 4, 9, BLACK),
    23.     ("a", 5, 9, BLACK),
    24.     ("e", 6, 9, BLACK),
    25.     ("h", 7, 9, BLACK),
    26.     ("r", 8, 9, BLACK),
    27.     ("c", 1, 7, BLACK),
    28.     ("c", 7, 7, BLACK),
    29.     ("p", 0, 6, BLACK),
    30.     ("p", 2, 6, BLACK),
    31.     ("p", 4, 6, BLACK),
    32.     ("p", 6, 6, BLACK),
    33.     ("p", 8, 6, BLACK),
    34. ]
    复制代码


    同时,把 draw_pieces 中的字体创建改为 `font = pygame.font.Font(None, 32)`,立即生效,不会报错。

    **如果你坚持要显示中文**:  
    1. 找一个中文字体文件(比如从 Windows 的 C:\Windows\Fonts 复制 simhei.ttf 到你项目目录)。  
    2. 确保运行代码时,当前工作目录确实包含该文件。最好把字体放在 Python 脚本同目录下,然后启动脚本时 cmd 切换到该目录。  
    3. 把 draw_board 和 draw_pieces 中的字体都改为 `pygame.font.Font("simhei.ttf", 30)` – 但记住字体名要完全匹配(包含扩展名)。  

    由于你的报错提示工作目录是 C:\Program Files\Python38,不建议把文件放那里。建议把棋子改为英文字母,这是最稳定、最简单的方法。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:24 | 显示全部楼层
    FishC 发表于 2026-7-5 09:15
    你的代码在 draw_pieces 中试图加载 "simhei.ttf" 文件,但你的工作目录是 C:\Program Files\Python38 ...

    复制显示不了
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:24 | 显示全部楼层
    过默 发表于 2026-07-05 09:24
    FishC 发表于 2026-7-5 09:15
    你的代码在 draw_piece ...


    请使用这个完全可运行的代码,棋子名称统一换成英文,无需任何字体文件。直接复制到你的Python文件,即可显示完整棋盘和棋子字母。


    import pygame
    import sys

    pygame.init()
    WIDTH, HEIGHT = 640, 720
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("Chinese Chess - Minimal")
    clock = pygame.time.Clock()

    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    BROWN = (200, 160, 100)
    RED = (200, 0, 0)

    MARGIN = 40
    SIZE = 60

    # 棋子数据:名字,列,行,颜色
    pieces = [
        ("R", 0, 0, RED), ("H", 1, 0, RED), ("E", 2, 0, RED), ("A", 3, 0, RED),
        ("K", 4, 0, RED), ("A", 5, 0, RED), ("E", 6, 0, RED), ("H", 7, 0, RED),
        ("R", 8, 0, RED),
        ("C", 1, 2, RED), ("C", 7, 2, RED),
        ("S", 0, 3, RED), ("S", 2, 3, RED), ("S", 4, 3, RED), ("S", 6, 3, RED), ("S", 8, 3, RED),
        ("r", 0, 9, BLACK), ("h", 1, 9, BLACK), ("e", 2, 9, BLACK), ("a", 3, 9, BLACK),
        ("k", 4, 9, BLACK), ("a", 5, 9, BLACK), ("e", 6, 9, BLACK), ("h", 7, 9, BLACK),
        ("r", 8, 9, BLACK),
        ("c", 1, 7, BLACK), ("c", 7, 7, BLACK),
        ("s", 0, 6, BLACK), ("s", 2, 6, BLACK), ("s", 4, 6, BLACK), ("s", 6, 6, BLACK), ("s", 8, 6, BLACK)
    ]

    def draw_board():
        screen.fill(BROWN)
        # 横线
        for row in range(10):
            y = MARGIN + row * SIZE
            pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)
        # 竖线(注意左右边界完整,中间断河界)
        for col in range(9):
            x = MARGIN + col * SIZE
            top = MARGIN
            bottom = MARGIN + 9 * SIZE
            if col == 0 or col == 8:
                pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)
            else:
                # 上半部分(0-4行)
                pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
                # 下半部分(5-9行)
                pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)
        # 九宫斜线 (左上右下,共四个宫)
        for (left, top) in [(MARGIN + 3*SIZE, MARGIN), (MARGIN + 3*SIZE, MARGIN + 7*SIZE)]:
            right = left + 2 * SIZE
            bottom = top + 2 * SIZE
            pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)
            pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)
        # 楚河汉界文字(用英文)
        font = pygame.font.Font(None, 30)
        text1 = font.render("CHU HE", True, BLACK)
        text2 = font.render("HAN JIE", True, BLACK)
        screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))
        screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))

    def draw_pieces():
        font = pygame.font.Font(None, 32)
        for name, col, row, color in pieces:
            x = MARGIN + col * SIZE
            y = MARGIN + row * SIZE
            pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)
            pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)
            text = font.render(name, True, color)
            text_rect = text.get_rect(center=(x, y))
            screen.blit(text, text_rect)

    def main():
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
            draw_board()
            draw_pieces()
            pygame.display.flip()
            clock.tick(30)
        pygame.quit()
        sys.exit()

    if __name__ == "__main__":
        main()


    复制上面的完整代码,保存为 .py 文件(例如 chess.py),直接运行即可看到带英文棋子字母的棋盘。所有棋子均显示字母,不会缺字。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:30 | 显示全部楼层
    FishC 发表于 2026-7-5 09:24
    请使用这个完全可运行的代码,棋子名称统一换成英文,无需任何字体文件。直接复制到你的Python文件,即 ...

    棋子怎么移动呢
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:30 | 显示全部楼层
    过默 发表于 2026-07-05 09:30
    FishC 发表于 2026-7-5 09:24
    请使用这个完全可运行 ...


    棋子移动的基本逻辑分三步:

    1. 点击选中棋子
    2. 点击目标位置
    3. 判断移动是否合法,若合法则更新棋子位置

    下面是用鼠标实现移动的核心代码框架(接你现有的代码,在 main 循环中添加事件处理):

    1. # 全局变量
    2. selected_piece = None     # 当前选中的棋子索引
    3. turn = 'red'              # 当前走棋方

    4. def get_click_pos(mouse_pos):
    5.     """将鼠标坐标转换为棋盘行列(col, row)"""
    6.     x, y = mouse_pos
    7.     col = round((x - MARGIN) / SIZE)
    8.     row = round((y - MARGIN) / SIZE)
    9.     # 边界检查
    10.     if 0 <= col <= 8 and 0 <= row <= 9:
    11.         return col, row
    12.     return None

    13. def is_legal_move(piece, from_col, from_row, to_col, to_row):
    14.     """简单判断:目标不是己方棋子即可(实际应加上具体棋规)"""
    15.     for p in pieces:
    16.         if p[1] == to_col and p[2] == to_row:
    17.             if p[3] == piece[3]:   # 同色
    18.                 return False
    19.     return True

    20. def move_piece(piece, to_col, to_row):
    21.     """更新棋子位置(同时吃掉目标棋子)"""
    22.     # 移除被吃棋子
    23.     for p in pieces[:]:
    24.         if p[1] == to_col and p[2] == to_row and p[3] != piece[3]:
    25.             pieces.remove(p)
    26.     # 更新选中棋子位置
    27.     piece[1] = to_col
    28.     piece[2] = to_row

    29. # 在 main 循环的事件处理中:
    30. for event in pygame.event.get():
    31.     if event.type == pygame.QUIT:
    32.         running = False
    33.     elif event.type == pygame.MOUSEBUTTONDOWN:
    34.         pos = get_click_pos(event.pos)
    35.         if pos is None:
    36.             continue
    37.         col, row = pos
    38.         # 查找点击位置是否有棋子
    39.         clicked_piece = None
    40.         for i, p in enumerate(pieces):
    41.             if p[1] == col and p[2] == row:
    42.                 clicked_piece = i
    43.                 break
    44.         if selected_piece is None:
    45.             # 未选中棋子,且点击到当前方棋子则选中
    46.             if clicked_piece is not None and pieces[clicked_piece][3] == turn_color:
    47.                 selected_piece = clicked_piece
    48.                 print("选中", pieces[selected_piece][0])
    49.         else:
    50.             # 已经选中,尝试移动
    51.             piece = pieces[selected_piece]
    52.             if is_legal_move(piece, piece[1], piece[2], col, row):
    53.                 move_piece(piece, col, row)
    54.                 # 切换走棋方
    55.                 turn = 'black' if turn == 'red' else 'red'
    56.                 print("移动成功")
    57.             else:
    58.                 # 如果点击了己方另一棋子,切换选中
    59.                 if clicked_piece is not None and pieces[clicked_piece][3] == turn_color:
    60.                     selected_piece = clicked_piece
    61.                     print("切换选中")
    62.                 else:
    63.                     selected_piece = None
    64.             # 移动后取消选中
    65.             selected_piece = None
    复制代码


    说明:
    - 需在代码顶部定义 turn_color 为 'red' 或 'black'(与 pieces 中颜色值保持一致)
    - 上述 is_legal_move 仅为示例,你应该补充完整象棋规则(如马脚、象田、炮隔子等)
    - 移动时直接修改 pieces 列表中的位置数据,draw_pieces 会根据新数据重绘

    将这段代码整合到你的 main 函数中的事件循环里,即可实现选棋、移动、吃子。注意需将 pieces 列表中的颜色值统一为 'red' 和 'black'(或对应 RGB 数值),以便 turn_color 比较。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:34 | 显示全部楼层
    FishC 发表于 2026-7-5 09:30
    棋子移动的基本逻辑分三步:

    1. 点击选中棋子

    复制到哪里,

    1. import pygame
    2. import sys

    3. pygame.init()
    4. WIDTH, HEIGHT = 640, 720
    5. screen = pygame.display.set_mode((WIDTH, HEIGHT))
    6. pygame.display.set_caption("中国象棋 - 极简版")
    7. clock = pygame.time.Clock()

    8. WHITE = (255, 255, 255)
    9. BLACK = (0, 0, 0)
    10. BROWN = (200, 160, 100)
    11. RED = (200, 0, 0)

    12. MARGIN = 40
    13. SIZE = 60
    14. COLS = 8
    15. ROWS = 9

    16. pieces = [
    17.     ("R", 0, 0, RED),   # 红车
    18.     ("H", 1, 0, RED),   # 红马
    19.     ("E", 2, 0, RED),   # 红象
    20.     ("A", 3, 0, RED),   # 红士
    21.     ("K", 4, 0, RED),   # 红帅
    22.     ("A", 5, 0, RED),
    23.     ("E", 6, 0, RED),
    24.     ("H", 7, 0, RED),
    25.     ("R", 8, 0, RED),
    26.     ("C", 1, 2, RED),   # 红炮
    27.     ("C", 7, 2, RED),
    28.     ("P", 0, 3, RED),   # 红兵
    29.     ("P", 2, 3, RED),
    30.     ("P", 4, 3, RED),
    31.     ("P", 6, 3, RED),
    32.     ("P", 8, 3, RED),
    33.     ("r", 0, 9, BLACK), # 黑车
    34.     ("h", 1, 9, BLACK),
    35.     ("e", 2, 9, BLACK),
    36.     ("a", 3, 9, BLACK),
    37.     ("k", 4, 9, BLACK),
    38.     ("a", 5, 9, BLACK),
    39.     ("e", 6, 9, BLACK),
    40.     ("h", 7, 9, BLACK),
    41.     ("r", 8, 9, BLACK),
    42.     ("c", 1, 7, BLACK),
    43.     ("c", 7, 7, BLACK),
    44.     ("p", 0, 6, BLACK),
    45.     ("p", 2, 6, BLACK),
    46.     ("p", 4, 6, BLACK),
    47.     ("p", 6, 6, BLACK),
    48.     ("p", 8, 6, BLACK),
    49. ]

    50. def draw_board():
    51.     screen.fill(BROWN)
    52.     for row in range(10):
    53.         y = MARGIN + row * SIZE
    54.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)
    55.     for col in range(9):
    56.         x = MARGIN + col * SIZE
    57.         top = MARGIN
    58.         bottom = MARGIN + 9 * SIZE
    59.         if col == 0 or col == 8:
    60.             pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)
    61.         else:
    62.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
    63.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)
    64.     for (left, top) in [(MARGIN + 3*SIZE, MARGIN), (MARGIN + 3*SIZE, MARGIN + 7*SIZE)]:
    65.         right = left + 2 * SIZE
    66.         bottom = top + 2 * SIZE
    67.         pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)
    68.         pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)
    69.     font = pygame.font.Font("simsunb.ttf", 30)
    70.     text1 = font.render("CHU HE", True, BLACK)
    71.     text2 = font.render("HAN JIE", True, BLACK)
    72.     screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))
    73.     screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))

    74. def draw_pieces():
    75.     font = pygame.font.Font(None, 32)
    76.     for name, col, row, color in pieces:
    77.         x = MARGIN + col * SIZE
    78.         y = MARGIN + row * SIZE
    79.         pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)
    80.         pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)
    81.         text = font.render(name, True, color)
    82.         text_rect = text.get_rect(center=(x, y))
    83.         screen.blit(text, text_rect)

    84. def main():
    85.     running = True
    86.     while running:
    87.         for event in pygame.event.get():
    88.             if event.type == pygame.QUIT:
    89.                 running = False
    90.         draw_board()
    91.         draw_pieces()
    92.         pygame.display.flip()
    93.         clock.tick(30)
    94.     pygame.quit()
    95.     sys.exit()

    96. if __name__ == "__main__":
    97.     main()
    复制代码
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:34 | 显示全部楼层
    过默 发表于 2026-07-05 09:34
    FishC 发表于 2026-7-5 09:30
    棋子移动的基本逻辑分 ...


    将棋子移动逻辑复制到你的代码中,步骤如下:  

    1. 打开你现有的代码文件(例如 qipan.py)。  
    2. 在 **draw_pieces 函数后面、main 函数前面**,插入移动相关的全局变量和函数(get_click_pos、handle_click、move_piece)。  
    3. 修改 main 函数中的事件循环,加入鼠标点击处理。  
    4. 把字体改为默认(pygame.font.Font(None, 30)),或者改为英文字母显示棋子(否则中文棋子无法显示)。  

    下面是一个整合了移动逻辑的完整代码(棋子名称改为英文,直接可用):  

    1. import pygame  
    2. import sys  

    3. pygame.init()  
    4. WIDTH, HEIGHT = 640, 720  
    5. screen = pygame.display.set_mode((WIDTH, HEIGHT))  
    6. pygame.display.set_caption("Chinese Chess")  
    7. clock = pygame.time.Clock()  

    8. WHITE = (255, 255, 255)  
    9. BLACK = (0, 0, 0)  
    10. BROWN = (200, 160, 100)  
    11. RED = (200, 0, 0)  

    12. MARGIN = 40  
    13. SIZE = 60  

    14. # 棋子数据:名字,列,行,颜色  
    15. pieces =  [  
    16.     ("R", 0, 0, BLACK), ("H", 1, 0, BLACK), ("E", 2, 0, BLACK),  
    17.     ("A", 3, 0, BLACK), ("K", 4, 0, BLACK), ("A", 5, 0, BLACK),  
    18.     ("E", 6, 0, BLACK), ("H", 7, 0, BLACK), ("R", 8, 0, BLACK),  
    19.     ("C", 1, 2, BLACK), ("C", 7, 2, BLACK),  
    20.     ("P", 0, 3, BLACK), ("P", 2, 3, BLACK), ("P", 4, 3, BLACK),  
    21.     ("P", 6, 3, BLACK), ("P", 8, 3, BLACK),  
    22.     ("R", 0, 9, RED), ("H", 1, 9, RED), ("E", 2, 9, RED),  
    23.     ("A", 3, 9, RED), ("K", 4, 9, RED), ("A", 5, 9, RED),  
    24.     ("E", 6, 9, RED), ("H", 7, 9, RED), ("R", 8, 9, RED),  
    25.     ("C", 1, 7, RED), ("C", 7, 7, RED),  
    26.     ("P", 0, 6, RED), ("P", 2, 6, RED), ("P", 4, 6, RED),  
    27.     ("P", 6, 6, RED), ("P", 8, 6, RED)  
    28. ]  

    29. selected_piece = None  
    30. turn = 'red'  

    31. def draw_board():  
    32.     screen.fill(BROWN)  
    33.     for row in range(10):  
    34.         y = MARGIN + row * SIZE  
    35.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)  
    36.     for col in range(9):  
    37.         x = MARGIN + col * SIZE  
    38.         top = MARGIN  
    39.         bottom = MARGIN + 9 * SIZE  
    40.         if col == 0 or col == 8:  
    41.             pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)  
    42.         else:  
    43.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)  
    44.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)  
    45.     for (left, top) in [(MARGIN + 3*SIZE, MARGIN), (MARGIN + 3*SIZE, MARGIN + 7*SIZE)]:  
    46.         right = left + 2 * SIZE  
    47.         bottom = top + 2 * SIZE  
    48.         pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)  
    49.         pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)  
    50.     font = pygame.font.Font(None, 30)  
    51.     text1 = font.render("CHU HE", True, BLACK)  
    52.     text2 = font.render("HAN JIE", True, BLACK)  
    53.     screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))  
    54.     screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))  

    55. def draw_pieces():  
    56.     font = pygame.font.Font(None, 32)  
    57.     for name, col, row, color in pieces:  
    58.         x = MARGIN + col * SIZE  
    59.         y = MARGIN + row * SIZE  
    60.         pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)  
    61.         pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)  
    62.         text = font.render(name, True, color)  
    63.         text_rect = text.get_rect(center=(x, y))  
    64.         screen.blit(text, text_rect)  

    65. # ---------- 移动逻辑开始 ----------  
    66. def get_click_pos(mouse_pos):  
    67.     x, y = mouse_pos  
    68.     col = round((x - MARGIN) / SIZE)  
    69.     row = round((y - MARGIN) / SIZE)  
    70.     if 0 <= col <= 8 and 0 <= row <= 9:  
    71.         return col, row  
    72.     return None  

    73. def handle_click(col, row):  
    74.     global selected_piece, turn  
    75.     # 检查点击位置是否有棋子  
    76.     index = None  
    77.     for i, (name, pc, pr, pcolor) in enumerate(pieces):  
    78.         if pc == col and pr == row:  
    79.             index = i  
    80.             break  
    81.     if selected_piece is None:  
    82.         # 没有选中任何棋子,尝试选中一个己方棋子  
    83.         if index is not None and pieces[index][3] == (RED if turn == 'red' else BLACK):  
    84.             selected_piece = index  
    85.     else:  
    86.         # 已选中一个棋子,尝试移动  
    87.         name, sc, sr, scolor = pieces[selected_piece]  
    88.         # 简单判断:不能吃己方棋子  
    89.         if index is not None and pieces[index][3] == scolor:  
    90.             # 点击了己方另一个棋子,切换选择  
    91.             selected_piece = index  
    92.             return  
    93.         # 执行移动(不校验规则)  
    94.         pieces[selected_piece] = (name, col, row, scolor)  
    95.         # 如果目标有对方棋子,吃掉  
    96.         if index is not None and pieces[index][3] != scolor:  
    97.             pieces.pop(index)  
    98.         # 切换回合  
    99.         turn = 'black' if turn == 'red' else 'red'  
    100.         selected_piece = None  

    101. def main():  
    102.     global selected_piece, turn  
    103.     running = True  
    104.     while running:  
    105.         for event in pygame.event.get():  
    106.             if event.type == pygame.QUIT:  
    107.                 running = False  
    108.             if event.type == pygame.MOUSEBUTTONDOWN:  
    109.                 if event.button == 1:  # 左键  
    110.                     pos = get_click_pos(event.pos)  
    111.                     if pos is not None:  
    112.                         handle_click(pos[0], pos[1])  
    113.         draw_board()  
    114.         # 高亮选中的棋子  
    115.         if selected_piece is not None:  
    116.             name, col, row, color = pieces[selected_piece]  
    117.             x = MARGIN + col * SIZE  
    118.             y = MARGIN + row * SIZE  
    119.             pygame.draw.circle(screen, (255, 255, 0), (x, y), SIZE // 2 - 2, 3)  
    120.         draw_pieces()  
    121.         pygame.display.flip()  
    122.         clock.tick(30)  
    123.     pygame.quit()  
    124.     sys.exit()  

    125. if __name__ == "__main__":  
    126.     main()  
    复制代码


    **使用方法**:  
    - 直接复制整个代码,保存为 .py 文件并运行。  
    - 点击红色或黑色棋子(英文字母代表:R=车,H=马,E=象,A=士,K=将,C=炮,P=兵),再点击目标格子即可移动。  
    - 左键点击选中,黄色圆圈表示选中状态。  
    - 移动后自动切换回合(红先黑后)。  

    **注意**:  
    - 该代码未实现中国象棋规则(如马脚、象田等),仅演示移动逻辑。  
    - 棋子使用英文缩写,无需字体文件。若想显示中文,可下载 SimSun.ttf 并修改字体加载。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:36 | 显示全部楼层
    FishC 发表于 2026-7-5 09:34
    将棋子移动逻辑复制到你的代码中,步骤如下:  

    1. 打开你现有的代码文件(例如 qipan.py)。  

    怎么吃子呢
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:37 | 显示全部楼层
    过默 发表于 2026-07-05 09:36
    FishC 发表于 2026-7-5 09:34
    将棋子移动逻辑复制到 ...


    吃子逻辑很简单:在你移动棋子的代码中,当判断目标位置有棋子时,先判断颜色是否不同(即敌方棋子),如果是,则从 pieces 列表中删除那个敌方棋子,再移动自己的棋子到该位置。

    下面是具体修改步骤(接你已有的移动代码,在 move_piece 函数中添加处理):

    原来 move_piece 的代码大致是:

    def move_piece(start_idx, end_col, end_row):
        global pieces
        name, col, row, color = pieces[start_idx]
        pieces[start_idx] = (name, end_col, end_row, color)

    现在加入吃子判断,变为:

    def move_piece(start_idx, end_col, end_row):
        global pieces, turn
        # 找到目标位置的棋子索引
        target_idx = None
        for i, (name, c, r, color) in enumerate(pieces):
            if c == end_col and r == end_row:
                target_idx = i
                break

        # 如果目标位置有棋子
        if target_idx is not None:
            target_color = pieces[target_idx][3]
            my_color = pieces[start_idx][3]
            if target_color != my_color:   # 吃子
                pieces.pop(target_idx)     # 移除敌方棋子
                # 注意:pop 后索引变化,需要重新调整 start_idx
                # 因为 target_idx < start_idx 时,start_idx 会减一
                if target_idx < start_idx:
                    start_idx -= 1
                # 移动自己的棋子
                name, col, row, color = pieces[start_idx]
                pieces[start_idx] = (name, end_col, end_row, color)
            else:
                # 这里是友方棋子,不能移动(可以忽略或给出提示)
                return False
        else:
            # 空位,直接移动
            name, col, row, color = pieces[start_idx]
            pieces[start_idx] = (name, end_col, end_row, color)
        return True

    注意:由于 pieces 列表可能变化,最好先记录原索引对应的棋子信息,然后更新。更稳妥的做法是:

    def move_piece(start_idx, end_col, end_row):
        global pieces, turn
        # 保存当前选中棋子的信息
        name, col, row, color = pieces[start_idx]
        # 检查目标位置
        target_idx = None
        for i, (n, c, r, colr) in enumerate(pieces):
            if c == end_col and r == end_row:
                target_idx = i
                break
        if target_idx is not None:
            target_color = pieces[target_idx][3]
            if target_color == color:  # 己方棋子,不能走
                return False
            else:
                # 吃子:先删除敌方棋子,再移动己方
                pieces.pop(target_idx)
                # 删除后原来的 start_idx 可能变化
                # 重新找到自己的索引
                new_idx = None
                for i, (n, c, r, colr) in enumerate(pieces):
                    if c == col and r == row and colr == color:
                        new_idx = i
                        break
                if new_idx is not None:
                    pieces[new_idx] = (name, end_col, end_row, color)
        else:
            # 空位,直接移动
            pieces[start_idx] = (name, end_col, end_row, color)
        return True

    这样更健壮。如果你之前的移动代码已经处理了索引变化,也可以直接用更简单的版本:

    def move_piece(start_idx, end_col, end_row):
        global pieces
        name, col, row, color = pieces[start_idx]
        # 判断是否能吃子
        for i, (n, c, r, colr) in enumerate(pieces):
            if c == end_col and r == end_row:
                if colr != color:  # 敌方
                    pieces.pop(i)
                    # 因为i可能小于start_idx,需要调整
                    if i < start_idx:
                        start_idx -= 1
                    pieces[start_idx] = (name, end_col, end_row, color)
                    return True
                else:
                    return False  # 友方不能吃
        # 空位
        pieces[start_idx] = (name, end_col, end_row, color)
        return True

    将以上代码替换你现有的 move_piece 函数即可。别忘了在 main 循环的点击事件中调用 move_piece 时,用返回值判断是否合法。如果返回 False,则当作无效点击,不清空选中。

    最终效果:点击自己的棋子,再点击敌方棋子所在位置,就会吃掉敌方棋子并移动到那里。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 09:42 | 显示全部楼层
    FishC 发表于 2026-7-5 09:37
    吃子逻辑很简单:在你移动棋子的代码中,当判断目标位置有棋子时,先判断颜色是否不同(即敌方棋子), ...
    1. import pygame  
    2. import sys  

    3. pygame.init()  
    4. WIDTH, HEIGHT = 640, 720  
    5. screen = pygame.display.set_mode((WIDTH, HEIGHT))  
    6. pygame.display.set_caption("Chinese Chess")  
    7. clock = pygame.time.Clock()  

    8. WHITE = (255, 255, 255)  
    9. BLACK = (0, 0, 0)  
    10. BROWN = (200, 160, 100)  
    11. RED = (200, 0, 0)  

    12. MARGIN = 40  
    13. SIZE = 60  

    14. # 棋子数据:名字,列,行,颜色  
    15. pieces =  [  
    16.     ("R", 0, 0, BLACK), ("H", 1, 0, BLACK), ("E", 2, 0, BLACK),  
    17.     ("A", 3, 0, BLACK), ("K", 4, 0, BLACK), ("A", 5, 0, BLACK),  
    18.     ("E", 6, 0, BLACK), ("H", 7, 0, BLACK), ("R", 8, 0, BLACK),  
    19.     ("C", 1, 2, BLACK), ("C", 7, 2, BLACK),  
    20.     ("P", 0, 3, BLACK), ("P", 2, 3, BLACK), ("P", 4, 3, BLACK),  
    21.     ("P", 6, 3, BLACK), ("P", 8, 3, BLACK),  
    22.     ("R", 0, 9, RED), ("H", 1, 9, RED), ("E", 2, 9, RED),  
    23.     ("A", 3, 9, RED), ("K", 4, 9, RED), ("A", 5, 9, RED),  
    24.     ("E", 6, 9, RED), ("H", 7, 9, RED), ("R", 8, 9, RED),  
    25.     ("C", 1, 7, RED), ("C", 7, 7, RED),  
    26.     ("P", 0, 6, RED), ("P", 2, 6, RED), ("P", 4, 6, RED),  
    27.     ("P", 6, 6, RED), ("P", 8, 6, RED)  
    28. ]  

    29. selected_piece = None  
    30. turn = 'red'  

    31. def draw_board():  
    32.     screen.fill(BROWN)  
    33.     for row in range(10):  
    34.         y = MARGIN + row * SIZE  
    35.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)  
    36.     for col in range(9):  
    37.         x = MARGIN + col * SIZE  
    38.         top = MARGIN  
    39.         bottom = MARGIN + 9 * SIZE  
    40.         if col == 0 or col == 8:  
    41.             pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)  
    42.         else:  
    43.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)  
    44.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)  
    45.     for (left, top) in [(MARGIN + 3*SIZE, MARGIN), (MARGIN + 3*SIZE, MARGIN + 7*SIZE)]:  
    46.         right = left + 2 * SIZE  
    47.         bottom = top + 2 * SIZE  
    48.         pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)  
    49.         pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)  
    50.     font = pygame.font.Font(None, 30)  
    51.     text1 = font.render("CHU HE", True, BLACK)  
    52.     text2 = font.render("HAN JIE", True, BLACK)  
    53.     screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))  
    54.     screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))  

    55. def draw_pieces():  
    56.     font = pygame.font.Font(None, 32)  
    57.     for name, col, row, color in pieces:  
    58.         x = MARGIN + col * SIZE  
    59.         y = MARGIN + row * SIZE  
    60.         pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)  
    61.         pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)  
    62.         text = font.render(name, True, color)  
    63.         text_rect = text.get_rect(center=(x, y))  
    64.         screen.blit(text, text_rect)  

    65. # ---------- 移动逻辑开始 ----------  
    66. def get_click_pos(mouse_pos):  
    67.     x, y = mouse_pos  
    68.     col = round((x - MARGIN) / SIZE)  
    69.     row = round((y - MARGIN) / SIZE)  
    70.     if 0 <= col <= 8 and 0 <= row <= 9:  
    71.         return col, row  
    72.     return None  

    73. def handle_click(col, row):  
    74.     global selected_piece, turn  
    75.     # 检查点击位置是否有棋子  
    76.     index = None  
    77.     for i, (name, pc, pr, pcolor) in enumerate(pieces):  
    78.         if pc == col and pr == row:  
    79.             index = i  
    80.             break  
    81.     if selected_piece is None:  
    82.         # 没有选中任何棋子,尝试选中一个己方棋子  
    83.         if index is not None and pieces[index][3] == (RED if turn == 'red' else BLACK):  
    84.             selected_piece = index  
    85.     else:  
    86.         # 已选中一个棋子,尝试移动  
    87.         name, sc, sr, scolor = pieces[selected_piece]  
    88.         # 简单判断:不能吃己方棋子  
    89.         if index is not None and pieces[index][3] == scolor:  
    90.             # 点击了己方另一个棋子,切换选择  
    91.             selected_piece = index  
    92.             return  
    93.         # 执行移动(不校验规则)  
    94.         pieces[selected_piece] = (name, col, row, scolor)  
    95.         # 如果目标有对方棋子,吃掉  
    96.         if index is not None and pieces[index][3] != scolor:  
    97.             pieces.pop(index)  
    98.         # 切换回合  
    99.         turn = 'black' if turn == 'red' else 'red'  
    100.         selected_piece = None
    101.         
    102. def move_piece(start_idx, end_col, end_row):
    103. &#160; global pieces
    104. &#160; &#160; name, col, row, color = pieces[start_idx]
    105. &#160; &#160; # 判断是否能吃子
    106. &#160; &#160; for i, (n, c, r, colr) in enumerate(pieces):
    107. &#160; &#160;&#160; &#160;&#160;&#160;if c == end_col and r == end_row:
    108. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;if colr != color:&#160;&#160;# 敌方
    109. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; pieces.pop(i)
    110. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; # 因为i可能小于start_idx,需要调整
    111. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; if i < start_idx:
    112. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160;&#160;start_idx -= 1
    113. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; pieces[start_idx] = (name, end_col, end_row, color)
    114. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; return True
    115. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;else:
    116. &#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160;&#160; &#160; return False&#160;&#160;# 友方不能吃
    117. &#160; &#160; # 空位
    118. &#160; &#160; pieces[start_idx] = (name, end_col, end_row, color)
    119. &#160; &#160; return True
    120. def main():  
    121.     global selected_piece, turn  
    122.     running = True  
    123.     while running:  
    124.         for event in pygame.event.get():  
    125.             if event.type == pygame.QUIT:  
    126.                 running = False  
    127.             if event.type == pygame.MOUSEBUTTONDOWN:  
    128.                 if event.button == 1:  # 左键  
    129.                     pos = get_click_pos(event.pos)  
    130.                     if pos is not None:  
    131.                         handle_click(pos[0], pos[1])  
    132.         draw_board()  
    133.         # 高亮选中的棋子  
    134.         if selected_piece is not None:  
    135.             name, col, row, color = pieces[selected_piece]  
    136.             x = MARGIN + col * SIZE  
    137.             y = MARGIN + row * SIZE  
    138.             pygame.draw.circle(screen, (255, 255, 0), (x, y), SIZE // 2 - 2, 3)  
    139.         draw_pieces()  
    140.         pygame.display.flip()  
    141.         clock.tick(30)  
    142.     pygame.quit()  
    143.     sys.exit()  

    144. if __name__ == "__main__":  
    145.     main()  
    复制代码

    怎么弄?什么main
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 09:42 | 显示全部楼层
    过默 发表于 2026-07-05 09:42
    FishC 发表于 2026-7-5 09:37
    吃子逻辑很简单:在你 ...


    你的代码不完整——从粘贴的内容看,你只复制到了 `get_click_pos` 函数的定义,缺少 `handle_click`、`move_piece` 以及修改后的 `main` 循环事件处理。所以运行后点击棋子没有反应。

    下面是一份 **完整可运行** 的代码(包含移动和吃子),你直接复制保存为 `chess.py` 并运行即可。棋子名字改为英文,不需要任何中文字体。


    1. import pygame
    2. import sys

    3. pygame.init()
    4. WIDTH, HEIGHT = 640, 720
    5. screen = pygame.display.set_mode((WIDTH, HEIGHT))
    6. pygame.display.set_caption("Chinese Chess - 带吃子")
    7. clock = pygame.time.Clock()

    8. WHITE = (255, 255, 255)
    9. BLACK = (0, 0, 0)
    10. BROWN = (200, 160, 100)
    11. RED = (200, 0, 0)

    12. MARGIN = 40
    13. SIZE = 60

    14. # 棋子数据:名字,列,行,颜色
    15. pieces = [
    16.     ('R', 0, 0, RED), ('H', 1, 0, RED), ('E', 2, 0, RED), ('A', 3, 0, RED),
    17.     ('K', 4, 0, RED), ('A', 5, 0, RED), ('E', 6, 0, RED), ('H', 7, 0, RED),
    18.     ('R', 8, 0, RED),
    19.     ('C', 1, 2, RED), ('C', 7, 2, RED),
    20.     ('P', 0, 3, RED), ('P', 2, 3, RED), ('P', 4, 3, RED), ('P', 6, 3, RED), ('P', 8, 3, RED),
    21.     ('r', 0, 9, BLACK), ('h', 1, 9, BLACK), ('e', 2, 9, BLACK), ('a', 3, 9, BLACK),
    22.     ('k', 4, 9, BLACK), ('a', 5, 9, BLACK), ('e', 6, 9, BLACK), ('h', 7, 9, BLACK),
    23.     ('r', 8, 9, BLACK),
    24.     ('c', 1, 7, BLACK), ('c', 7, 7, BLACK),
    25.     ('p', 0, 6, BLACK), ('p', 2, 6, BLACK), ('p', 4, 6, BLACK), ('p', 6, 6, BLACK), ('p', 8, 6, BLACK),
    26. ]

    27. selected_piece = None  # 当前选中棋子的索引
    28. turn = 'red'           # 'red' 或 'black'

    29. def draw_board():
    30.     screen.fill(BROWN)
    31.     for row in range(10):
    32.         y = MARGIN + row * SIZE
    33.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)
    34.     for col in range(9):
    35.         x = MARGIN + col * SIZE
    36.         top = MARGIN
    37.         bottom = MARGIN + 9 * SIZE
    38.         if col == 0 or col == 8:
    39.             pygame.draw.line(screen, BLACK, (x, top), (x, bottom), 2)
    40.         else:
    41.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
    42.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)
    43.     # 九宫斜线
    44.     for (left, top) in [(MARGIN + 3*SIZE, MARGIN), (MARGIN + 3*SIZE, MARGIN + 7*SIZE)]:
    45.         right = left + 2 * SIZE
    46.         bottom = top + 2 * SIZE
    47.         pygame.draw.line(screen, BLACK, (left, top), (right, bottom), 2)
    48.         pygame.draw.line(screen, BLACK, (left, bottom), (right, top), 2)
    49.     # 楚河汉界
    50.     font = pygame.font.Font(None, 30)
    51.     text1 = font.render("CHU HE", True, BLACK)
    52.     text2 = font.render("HAN JIE", True, BLACK)
    53.     screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))
    54.     screen.blit(text2, (MARGIN + 4.5 * SIZE, MARGIN + 4 * SIZE))

    55. def draw_pieces():
    56.     font = pygame.font.Font(None, 32)
    57.     for name, col, row, color in pieces:
    58.         x = MARGIN + col * SIZE
    59.         y = MARGIN + row * SIZE
    60.         pygame.draw.circle(screen, WHITE, (x, y), SIZE // 2 - 4)
    61.         pygame.draw.circle(screen, color, (x, y), SIZE // 2 - 4, 2)
    62.         text = font.render(name, True, color)
    63.         text_rect = text.get_rect(center=(x, y))
    64.         screen.blit(text, text_rect)

    65. def get_click_pos(mouse_pos):
    66.     x, y = mouse_pos
    67.     col = round((x - MARGIN) / SIZE)
    68.     row = round((y - MARGIN) / SIZE)
    69.     if 0 <= col <= 8 and 0 <= row <= 9:
    70.         return col, row
    71.     return None

    72. def get_piece_at(col, row):
    73.     for i, (n, c, r, colr) in enumerate(pieces):
    74.         if c == col and r == row:
    75.             return i, (n, colr)
    76.     return None, None

    77. def move_piece(start_idx, end_col, end_row):
    78.     global pieces, turn
    79.     name, col, row, color = pieces[start_idx]
    80.     # 检查目标位置
    81.     target_idx, target_info = get_piece_at(end_col, end_row)
    82.     if target_idx is not None:
    83.         target_color = target_info[1]
    84.         if target_color == color:
    85.             # 己方棋子,不能吃
    86.             return False
    87.         else:
    88.             # 吃子
    89.             pieces.pop(target_idx)
    90.             # 由于列表长度变化,调整 start_idx
    91.             if target_idx < start_idx:
    92.                 start_idx -= 1
    93.             pieces[start_idx] = (name, end_col, end_row, color)
    94.     else:
    95.         # 空位,直接移动
    96.         pieces[start_idx] = (name, end_col, end_row, color)
    97.     # 切换回合
    98.     turn = 'black' if turn == 'red' else 'red'
    99.     return True

    100. def handle_click(mouse_pos):
    101.     global selected_piece, turn
    102.     pos = get_click_pos(mouse_pos)
    103.     if pos is None:
    104.         return
    105.     col, row = pos
    106.     idx, info = get_piece_at(col, row)
    107.     if selected_piece is None:
    108.         # 没有选中任何棋子,尝试选中
    109.         if idx is not None:
    110.             name, color = info
    111.             # 检查是否轮到当前玩家
    112.             if (turn == 'red' and color == RED) or (turn == 'black' and color == BLACK):
    113.                 selected_piece = idx
    114.     else:
    115.         # 已经选中了一个棋子
    116.         if idx is not None:
    117.             name, color = info
    118.             # 如果点击的是己方棋子,则重新选中
    119.             if (turn == 'red' and color == RED) or (turn == 'black' and color == BLACK):
    120.                 selected_piece = idx
    121.                 return
    122.         # 尝试移动选中棋子到点击位置
    123.         if move_piece(selected_piece, col, row):
    124.             # 移动成功,清除选中状态
    125.             selected_piece = None
    126.         else:
    127.             # 移动失败(比如吃自己),保持选中
    128.             pass

    129. def main():
    130.     global selected_piece
    131.     running = True
    132.     while running:
    133.         for event in pygame.event.get():
    134.             if event.type == pygame.QUIT:
    135.                 running = False
    136.             if event.type == pygame.MOUSEBUTTONDOWN:
    137.                 if event.button == 1:  # 左键
    138.                     handle_click(event.pos)
    139.         draw_board()
    140.         draw_pieces()
    141.         pygame.display.flip()
    142.         clock.tick(30)
    143.     pygame.quit()
    144.     sys.exit()

    145. if __name__ == "__main__":
    146.     main()
    复制代码


    **使用方法**:  
    - 点击自己的棋子(红色大写字母 或 黑色小写字母)选中(被选中的棋子没有高亮,但你可以根据需要添加)。  
    - 再点击一个目标位置(空位或敌方棋子)即可移动或吃子。  
    - 回合会自动切换。

    注意:这里没有实现完整的象棋规则(例如马脚、炮架、将帅对面等),只实现了基本的点击移动和吃子。如果你需要完整规则,可以在此基础上扩展。

    如果运行后仍然是之前空白或缺少中文的界面,请确保你已经完全替换了这段代码。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

    GMT+8, 2026-7-6 03:10

    Powered by Discuz! X3.4

    © 2001-2023 Discuz! Team.

    快速回复 返回顶部 返回列表