过默 发表于 2026-7-5 08:59:53

怎么学象棋

象棋棋盘怎么用python代码写,棋盘横线怎么敲?

FishC 发表于 2026-7-5 09:00:29

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

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


# 静态棋盘(直接打印字符串)
board = """
┌─┬─┬─┬─┬─┬─┬─┬─┐
│ │ │ │╲│╱│ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │╱│╲│ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┴─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┬─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │ │
└─┴─┴─┴─┴─┴─┴─┴─┘
"""
print(board)


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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:05:52

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

pygame代码写象棋

FishC 发表于 2026-7-5 09:06:08

过默 发表于 2026-07-05 09:05
FishC 发表于 2026-7-5 09:00
如何学象棋
1. 先背 ...

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

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


import pygame
import sys

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

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

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

# 棋子数据示例(位置用行列表示)
pieces = [
    ("帅", 4, 0, RED), ("士", 3, 0, RED), ("相", 2, 0, RED),
    ("车", 0, 0, RED), ("马", 1, 0, RED), ("炮", 1, 2, RED),
    ("兵", 0, 3, RED), ("兵", 2, 3, RED), ("兵", 4, 3, RED),
    ("将", 4, 9, BLACK), ("士", 3, 9, BLACK), ("象", 2, 9, BLACK),
    ("车", 0, 9, BLACK), ("马", 1, 9, BLACK), ("炮", 1, 7, BLACK),
    ("卒", 0, 6, BLACK), ("卒", 2, 6, BLACK), ("卒", 4, 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)
    # 画竖线(注意第8列只有上下两段)
    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 [(3*SIZE+MARGIN, 0), (3*SIZE+MARGIN, 5*SIZE+MARGIN)]:
      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.SysFont("simhei", 30)
    text1 = font.render("楚 河", True, BLACK)
    text2 = font.render("汉 界", 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.SysFont("simhei", 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()


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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:08:03

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).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

FishC 发表于 2026-7-5 09:08:23

过默 发表于 2026-07-05 09:08
FishC 发表于 2026-7-5 09:06
用 Pygame 写中国象棋 ...

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

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


font = pygame.font.Font(None, 30)   # 在 draw_board 中使用
font = pygame.font.Font(None, 32)   # 在 draw_pieces 中使用


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

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

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


import pygame
import sys

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

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

MARGIN = 40
SIZE = 60
COLS = 8
ROWS = 9

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

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:
            pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
            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()


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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:11:24

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

几个棋子没显示字

FishC 发表于 2026-7-5 09:11:35

过默 发表于 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.ttf 或 msyh.ttc),放到代码同目录下,然后改为:
   font = pygame.font.Font("simhei.ttf", 32)
   这样就能正常显示中文棋子名称了。

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:15:06

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'.

FishC 发表于 2026-7-5 09:15:16

过默 发表于 2026-07-05 09:15
FishC 发表于 2026-7-5 09:11
你的问题可能是棋子名 ...

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

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

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

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),
    ("P", 0, 3, RED),   # 红兵
    ("P", 2, 3, RED),
    ("P", 4, 3, RED),
    ("P", 6, 3, RED),
    ("P", 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),
    ("p", 0, 6, BLACK),
    ("p", 2, 6, BLACK),
    ("p", 4, 6, BLACK),
    ("p", 6, 6, BLACK),
    ("p", 8, 6, BLACK),
]

同时,把 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 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:24:23

FishC 发表于 2026-7-5 09:15
你的代码在 draw_pieces 中试图加载 "simhei.ttf" 文件,但你的工作目录是 C:\Program Files\Python38 ...

复制显示不了

FishC 发表于 2026-7-5 09:24:39

过默 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:30:31

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

棋子怎么移动呢

FishC 发表于 2026-7-5 09:30:45

过默 发表于 2026-07-05 09:30
FishC 发表于 2026-7-5 09:24
请使用这个完全可运行 ...

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

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

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

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

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

def is_legal_move(piece, from_col, from_row, to_col, to_row):
    """简单判断:目标不是己方棋子即可(实际应加上具体棋规)"""
    for p in pieces:
      if p == to_col and p == to_row:
            if p == piece:   # 同色
                return False
    return True

def move_piece(piece, to_col, to_row):
    """更新棋子位置(同时吃掉目标棋子)"""
    # 移除被吃棋子
    for p in pieces[:]:
      if p == to_col and p == to_row and p != piece:
            pieces.remove(p)
    # 更新选中棋子位置
    piece = to_col
    piece = to_row

# 在 main 循环的事件处理中:
for event in pygame.event.get():
    if event.type == pygame.QUIT:
      running = False
    elif event.type == pygame.MOUSEBUTTONDOWN:
      pos = get_click_pos(event.pos)
      if pos is None:
            continue
      col, row = pos
      # 查找点击位置是否有棋子
      clicked_piece = None
      for i, p in enumerate(pieces):
            if p == col and p == row:
                clicked_piece = i
                break
      if selected_piece is None:
            # 未选中棋子,且点击到当前方棋子则选中
            if clicked_piece is not None and pieces == turn_color:
                selected_piece = clicked_piece
                print("选中", pieces)
      else:
            # 已经选中,尝试移动
            piece = pieces
            if is_legal_move(piece, piece, piece, col, row):
                move_piece(piece, col, row)
                # 切换走棋方
                turn = 'black' if turn == 'red' else 'red'
                print("移动成功")
            else:
                # 如果点击了己方另一棋子,切换选中
                if clicked_piece is not None and pieces == turn_color:
                  selected_piece = clicked_piece
                  print("切换选中")
                else:
                  selected_piece = None
            # 移动后取消选中
            selected_piece = None

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:34:21

FishC 发表于 2026-7-5 09:30
棋子移动的基本逻辑分三步:

1. 点击选中棋子


复制到哪里,
import pygame
import sys

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

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

MARGIN = 40
SIZE = 60
COLS = 8
ROWS = 9

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),
    ("P", 0, 3, RED),   # 红兵
    ("P", 2, 3, RED),
    ("P", 4, 3, RED),
    ("P", 6, 3, RED),
    ("P", 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),
    ("p", 0, 6, BLACK),
    ("p", 2, 6, BLACK),
    ("p", 4, 6, BLACK),
    ("p", 6, 6, BLACK),
    ("p", 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:
            pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
            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("simsunb.ttf", 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()

FishC 发表于 2026-7-5 09:34:46

过默 发表于 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)),或者改为英文字母显示棋子(否则中文棋子无法显示)。

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

import pygame
import sys

pygame.init()
WIDTH, HEIGHT = 640, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Chinese Chess")
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, BLACK), ("H", 1, 0, BLACK), ("E", 2, 0, BLACK),
    ("A", 3, 0, BLACK), ("K", 4, 0, BLACK), ("A", 5, 0, BLACK),
    ("E", 6, 0, BLACK), ("H", 7, 0, BLACK), ("R", 8, 0, BLACK),
    ("C", 1, 2, BLACK), ("C", 7, 2, BLACK),
    ("P", 0, 3, BLACK), ("P", 2, 3, BLACK), ("P", 4, 3, BLACK),
    ("P", 6, 3, BLACK), ("P", 8, 3, BLACK),
    ("R", 0, 9, RED), ("H", 1, 9, RED), ("E", 2, 9, RED),
    ("A", 3, 9, RED), ("K", 4, 9, RED), ("A", 5, 9, RED),
    ("E", 6, 9, RED), ("H", 7, 9, RED), ("R", 8, 9, RED),
    ("C", 1, 7, RED), ("C", 7, 7, RED),
    ("P", 0, 6, RED), ("P", 2, 6, RED), ("P", 4, 6, RED),
    ("P", 6, 6, RED), ("P", 8, 6, RED)
]

selected_piece = None
turn = 'red'

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:
            pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
            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 get_click_pos(mouse_pos):
    x, y = mouse_pos
    col = round((x - MARGIN) / SIZE)
    row = round((y - MARGIN) / SIZE)
    if 0 <= col <= 8 and 0 <= row <= 9:
      return col, row
    return None

def handle_click(col, row):
    global selected_piece, turn
    # 检查点击位置是否有棋子
    index = None
    for i, (name, pc, pr, pcolor) in enumerate(pieces):
      if pc == col and pr == row:
            index = i
            break
    if selected_piece is None:
      # 没有选中任何棋子,尝试选中一个己方棋子
      if index is not None and pieces == (RED if turn == 'red' else BLACK):
            selected_piece = index
    else:
      # 已选中一个棋子,尝试移动
      name, sc, sr, scolor = pieces
      # 简单判断:不能吃己方棋子
      if index is not None and pieces == scolor:
            # 点击了己方另一个棋子,切换选择
            selected_piece = index
            return
      # 执行移动(不校验规则)
      pieces = (name, col, row, scolor)
      # 如果目标有对方棋子,吃掉
      if index is not None and pieces != scolor:
            pieces.pop(index)
      # 切换回合
      turn = 'black' if turn == 'red' else 'red'
      selected_piece = None

def main():
    global selected_piece, turn
    running = True
    while running:
      for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:# 左键
                  pos = get_click_pos(event.pos)
                  if pos is not None:
                        handle_click(pos, pos)
      draw_board()
      # 高亮选中的棋子
      if selected_piece is not None:
            name, col, row, color = pieces
            x = MARGIN + col * SIZE
            y = MARGIN + row * SIZE
            pygame.draw.circle(screen, (255, 255, 0), (x, y), SIZE // 2 - 2, 3)
      draw_pieces()
      pygame.display.flip()
      clock.tick(30)
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()


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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:36:48

FishC 发表于 2026-7-5 09:34
将棋子移动逻辑复制到你的代码中,步骤如下:

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


怎么吃子呢

FishC 发表于 2026-7-5 09:37:02

过默 发表于 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
    pieces = (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
      my_color = pieces
      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
            pieces = (name, end_col, end_row, color)
      else:
            # 这里是友方棋子,不能移动(可以忽略或给出提示)
            return False
    else:
      # 空位,直接移动
      name, col, row, color = pieces
      pieces = (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
    # 检查目标位置
    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
      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 = (name, end_col, end_row, color)
    else:
      # 空位,直接移动
      pieces = (name, end_col, end_row, color)
    return True

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

def move_piece(start_idx, end_col, end_row):
    global pieces
    name, col, row, color = pieces
    # 判断是否能吃子
    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 = (name, end_col, end_row, color)
                return True
            else:
                return False# 友方不能吃
    # 空位
    pieces = (name, end_col, end_row, color)
    return True

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-5 09:42:08

FishC 发表于 2026-7-5 09:37
吃子逻辑很简单:在你移动棋子的代码中,当判断目标位置有棋子时,先判断颜色是否不同(即敌方棋子), ...

import pygame
import sys

pygame.init()
WIDTH, HEIGHT = 640, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Chinese Chess")
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, BLACK), ("H", 1, 0, BLACK), ("E", 2, 0, BLACK),
    ("A", 3, 0, BLACK), ("K", 4, 0, BLACK), ("A", 5, 0, BLACK),
    ("E", 6, 0, BLACK), ("H", 7, 0, BLACK), ("R", 8, 0, BLACK),
    ("C", 1, 2, BLACK), ("C", 7, 2, BLACK),
    ("P", 0, 3, BLACK), ("P", 2, 3, BLACK), ("P", 4, 3, BLACK),
    ("P", 6, 3, BLACK), ("P", 8, 3, BLACK),
    ("R", 0, 9, RED), ("H", 1, 9, RED), ("E", 2, 9, RED),
    ("A", 3, 9, RED), ("K", 4, 9, RED), ("A", 5, 9, RED),
    ("E", 6, 9, RED), ("H", 7, 9, RED), ("R", 8, 9, RED),
    ("C", 1, 7, RED), ("C", 7, 7, RED),
    ("P", 0, 6, RED), ("P", 2, 6, RED), ("P", 4, 6, RED),
    ("P", 6, 6, RED), ("P", 8, 6, RED)
]

selected_piece = None
turn = 'red'

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:
            pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
            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 get_click_pos(mouse_pos):
    x, y = mouse_pos
    col = round((x - MARGIN) / SIZE)
    row = round((y - MARGIN) / SIZE)
    if 0 <= col <= 8 and 0 <= row <= 9:
      return col, row
    return None

def handle_click(col, row):
    global selected_piece, turn
    # 检查点击位置是否有棋子
    index = None
    for i, (name, pc, pr, pcolor) in enumerate(pieces):
      if pc == col and pr == row:
            index = i
            break
    if selected_piece is None:
      # 没有选中任何棋子,尝试选中一个己方棋子
      if index is not None and pieces == (RED if turn == 'red' else BLACK):
            selected_piece = index
    else:
      # 已选中一个棋子,尝试移动
      name, sc, sr, scolor = pieces
      # 简单判断:不能吃己方棋子
      if index is not None and pieces == scolor:
            # 点击了己方另一个棋子,切换选择
            selected_piece = index
            return
      # 执行移动(不校验规则)
      pieces = (name, col, row, scolor)
      # 如果目标有对方棋子,吃掉
      if index is not None and pieces != scolor:
            pieces.pop(index)
      # 切换回合
      turn = 'black' if turn == 'red' else 'red'
      selected_piece = None
      
def move_piece(start_idx, end_col, end_row):
  global pieces
    name, col, row, color = pieces
    # 判断是否能吃子
    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 = (name, end_col, end_row, color)
                return True
            else:
                return False  # 友方不能吃
    # 空位
    pieces = (name, end_col, end_row, color)
    return True
def main():
    global selected_piece, turn
    running = True
    while running:
      for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:# 左键
                  pos = get_click_pos(event.pos)
                  if pos is not None:
                        handle_click(pos, pos)
      draw_board()
      # 高亮选中的棋子
      if selected_piece is not None:
            name, col, row, color = pieces
            x = MARGIN + col * SIZE
            y = MARGIN + row * SIZE
            pygame.draw.circle(screen, (255, 255, 0), (x, y), SIZE // 2 - 2, 3)
      draw_pieces()
      pygame.display.flip()
      clock.tick(30)
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

怎么弄?什么main

FishC 发表于 2026-7-5 09:42:28

过默 发表于 2026-07-05 09:42
FishC 发表于 2026-7-5 09:37
吃子逻辑很简单:在你 ...

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

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


import pygame
import sys

pygame.init()
WIDTH, HEIGHT = 640, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Chinese Chess - 带吃子")
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),
    ('P', 0, 3, RED), ('P', 2, 3, RED), ('P', 4, 3, RED), ('P', 6, 3, RED), ('P', 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),
    ('p', 0, 6, BLACK), ('p', 2, 6, BLACK), ('p', 4, 6, BLACK), ('p', 6, 6, BLACK), ('p', 8, 6, BLACK),
]

selected_piece = None# 当前选中棋子的索引
turn = 'red'         # 'red' 或 '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:
            pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
            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 get_click_pos(mouse_pos):
    x, y = mouse_pos
    col = round((x - MARGIN) / SIZE)
    row = round((y - MARGIN) / SIZE)
    if 0 <= col <= 8 and 0 <= row <= 9:
      return col, row
    return None

def get_piece_at(col, row):
    for i, (n, c, r, colr) in enumerate(pieces):
      if c == col and r == row:
            return i, (n, colr)
    return None, None

def move_piece(start_idx, end_col, end_row):
    global pieces, turn
    name, col, row, color = pieces
    # 检查目标位置
    target_idx, target_info = get_piece_at(end_col, end_row)
    if target_idx is not None:
      target_color = target_info
      if target_color == color:
            # 己方棋子,不能吃
            return False
      else:
            # 吃子
            pieces.pop(target_idx)
            # 由于列表长度变化,调整 start_idx
            if target_idx < start_idx:
                start_idx -= 1
            pieces = (name, end_col, end_row, color)
    else:
      # 空位,直接移动
      pieces = (name, end_col, end_row, color)
    # 切换回合
    turn = 'black' if turn == 'red' else 'red'
    return True

def handle_click(mouse_pos):
    global selected_piece, turn
    pos = get_click_pos(mouse_pos)
    if pos is None:
      return
    col, row = pos
    idx, info = get_piece_at(col, row)
    if selected_piece is None:
      # 没有选中任何棋子,尝试选中
      if idx is not None:
            name, color = info
            # 检查是否轮到当前玩家
            if (turn == 'red' and color == RED) or (turn == 'black' and color == BLACK):
                selected_piece = idx
    else:
      # 已经选中了一个棋子
      if idx is not None:
            name, color = info
            # 如果点击的是己方棋子,则重新选中
            if (turn == 'red' and color == RED) or (turn == 'black' and color == BLACK):
                selected_piece = idx
                return
      # 尝试移动选中棋子到点击位置
      if move_piece(selected_piece, col, row):
            # 移动成功,清除选中状态
            selected_piece = None
      else:
            # 移动失败(比如吃自己),保持选中
            pass

def main():
    global selected_piece
    running = True
    while running:
      for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:# 左键
                  handle_click(event.pos)
      draw_board()
      draw_pieces()
      pygame.display.flip()
      clock.tick(30)
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()


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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1] 2 3 4
查看完整版本: 怎么学象棋