过默 发表于 2026-7-5 11:45:50

过默 发表于 2026-7-5 11:43
Traceback (most recent call last):
File "C:\Program Files\Python38\qipan.py", line 176, in
   ...

import pygame
import sys

pygame.init()
WIDTH, HEIGHT = 640, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Chinese Chess - Full")
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), ('马', 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)
]

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),
                        (MARGIN + 3 * SIZE, MARGIN + 7 * SIZE), (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("simsun", 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, None

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

    # ----------------- 走法合法性检查 -----------------
    def is_valid_move(name, col, row, end_col, end_row, pieces_list):
      dx = end_col - col
      dy = end_row - row
      # 马走日字
      if name in ('M', 'H'):# 根据你的棋子名字调整,红马='M',黑马='H'
            if (abs(dx), abs(dy)) not in [(1,2), (2,1)]:
                return False# 不是日字
            # 计算蹩马腿位置
            if abs(dx) == 1:# 横向走1,纵向走2
                leg_col, leg_row = col, row + dy//2
            else:             # 横向走2,纵向走1
                leg_col, leg_row = col + dx//2, row
            # 检查该位置是否有棋子
            for (n, c, r, clr) in pieces_list:
                if c == leg_col and r == leg_row:
                  return False# 蹩马腿
            return True
      else:
            # 其他棋子暂时允许任意移动(后续可扩展)
            return True

    if not is_valid_move(name, col, row, end_col, end_row, pieces):
      return False# 不合法,取消移动

    # ----------------- 执行移动(含吃子) -----------------
    if target_idx is not None:
      target_color = pieces
      if target_color != color:# 吃子
            pieces.pop(target_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)
            return True
      else:
            return False# 不能吃己方棋子
    else:
      # 空位直接移动
      pieces = (name, end_col, end_row, color)
      return True

def handle_click(mouse_pos):
    global selected_piece, turn
    click_col, click_row = get_click_pos(mouse_pos)
    if click_col is None:
      return
    if selected_piece is None:
      # 尝试选中当前回合方的棋子
      for i, (name, col, row, color) in enumerate(pieces):
            if col == click_col and row == click_row:
                if (turn == 'red' and color == RED) or (turn == 'black' and color == BLACK):
                  selected_piece = i
                break
    else:
      # 尝试移动
      if move_piece(selected_piece, click_col, click_row):
            # 成功移动,切换回合
            turn = 'black' if turn == 'red' else 'red'
      # 无论移动成功与否,清除选中状态
      selected_piece = None

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

if __name__ == "__main__":
    main()

Traceback (most recent call last):
File "C:\Program Files\Python38\qipan.py", line 176, in <module>
    main()
File "C:\Program Files\Python38\qipan.py", line 169, in main
    draw_pieces()
File "C:\Program Files\Python38\qipan.py", line 66, in draw_pieces
    font = pygame.font.Font("simsun", 32)
FileNotFoundError: No file 'simsun' found in working directory 'C:\Program Files\Python38'.
>>>

过默 发表于 2026-7-5 12:13:32

过默 发表于 2026-7-5 11:45
Traceback (most recent call last):
File "C:\Program Files\Python38\qipan.py", line 176, in
...

import pygame
import sys

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

WHITE=
是什么?怎么调用显示棋盘

过默 发表于 2026-7-5 13:01:57

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

怎么下载,pip安装字体吗

FishC 发表于 2026-7-5 13:02:04

过默 发表于 2026-07-05 13:01
FishC 发表于 2026-7-5 09:08
这个错误是因为在调用...

不是 pip 安装,字体是系统文件,不是 Python 模块。你需要手动下载一个中文字体文件,比如 “simhei.ttf”(黑体)或 “msyh.ttf”(微软雅黑)。把下载好的 .ttf 文件放到你的 Python 脚本同一个文件夹里(或者指定路径)。然后用 pygame.font.Font("simhei.ttf", 30) 替换原来的 pygame.font.SysFont。

如果不想下载,也可以直接用系统里已有的字体文件路径。Windows 下通常有:


font = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 30)


Mac 或 Linux 路径不同,请自行百度搜索。这样就能显示中文了。

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

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

FishC 发表于 2026-7-5 13:02
不是 pip 安装,字体是系统文件,不是 Python 模块。你需要手动下载一个中文字体文件,比如 “simhei.t ...


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.Font("C:/Windows/Fonts/simhei.ttf", 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.Font("C:/Windows/Fonts/simhei.ttf", 30)

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

只显示一半棋子了,上面有两根斜线

过默 发表于 2026-7-5 13:23:57

FishC 发表于 2026-7-5 13:02
不是 pip 安装,字体是系统文件,不是 Python 模块。你需要手动下载一个中文字体文件,比如 “simhei.t ...


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.Font("C:/Windows/Fonts/simhei.ttf", 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.Font("C:/Windows/Fonts/simhei.ttf", 30)

    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 13:24:11

过默 发表于 2026-07-05 13:23
FishC 发表于 2026-7-5 13:02
不是 pip 安装,字体是 ...

你的代码目前只画了棋盘和棋子,没有写任何吃子判断或胜负规则。所以“卒把帅吃了”只是画面上被覆盖,程序并不知道游戏结束。你需要添加一个检测函数,每次移动后检查对方的帅(将)是否还在棋盘上。

简单方法:在 pieces 列表里,每次走棋后遍历,看是否还有“帅”或“将”。如果对方已经没了,就弹出胜利提示。

例如:


def check_winner(pieces):
    red_king = any(p == '帅' for p in pieces)
    black_king = any(p == '将' for p in pieces)
    if not red_king:
      return "黑方胜!"
    if not black_king:
      return "红方胜!"
    return None


在你的主循环中,每次移动后调用这个函数,如果返回非 None,就用 pygame 显示文字并暂停游戏。

另外,你提到的“卒走过了河可以横吃”等规则,也只是视觉上画了,没有逻辑实现。建议先做一个简单的【点击选择 - 点击移动】交互框架,每一步都验证合法性。

如果想快速看到效果,可以先在 draw_pieces 里临时硬编码一个测试:初始就把黑将去掉,看提示是否弹出。调试通过后再完善真实走法。

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