鱼C论坛

 找回密码
 立即注册
楼主: 过默

怎么学象棋

[复制链接]
 楼主| 发表于 1 小时前 | 显示全部楼层
FishC 发表于 2026-7-5 10:41
您可能想上传象棋软件的截图,但在Discuz!论坛中上传图片需要使用帖子编辑区的“附件”或“图片”按钮 ...

点击了,看不了图片吗?

点击了,看不了图片吗?


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

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 10:44
FishC 发表于 2026-7-5 10:41
您可能想上传象棋软件 ...


您可能遇到了上传图片的问题。在 Discuz! 论坛中,上传图片需要点击编辑器上方的 **“附件”** 或 **“图片”** 按钮(通常是一个回形针或山形图标)。如果按钮无效,请检查您的用户等级是否有上传权限,或者尝试更换浏览器。

如果您是想展示棋盘上出现了四个九宫格的截图,可以这样操作:

1. 将棋盘截图保存为 PNG 或 JPG 文件。
2. 在发帖时,点击编辑器工具栏的 **“附件”** 按钮,选择该图片文件上传。
3. 上传成功后,将图片代码插入到帖子正文中(如 ` `)。

如果还是无法上传,您也可以直接将截图文件通过邮箱或网盘链接发送,或者用文字描述您看到的棋盘布局(例如“红方和黑方各有两个斜线格子”)。

我们上次提到棋盘上“四个九宫格”是因为您错误地绘制了九宫斜线位置。正确的代码应该只画两个九宫(红方一个、黑方一个)。如果您把代码中的 `for (left, top) in` 中的四个坐标改成了两个,即 ` `,就不会再有多余的格子了。

如果您需要进一步的代码修改指导,请告诉我。

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

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层
不是图片吗,我这显示了图片
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 10:45
不是图片吗,我这显示了图片


您说的对,您可能在论坛上传了图片,但我是文本AI,无法查看任何上传的图片或附件。请您直接用文字描述您看到的棋盘问题(例如“马走日没生效”或“四个九宫格画在哪里”),我会继续帮您修改代码。如果您想展示代码运行结果,也可以直接描述“棋子能移动但马乱跳”之类的现象。

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

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层
FishC 发表于 2026-7-5 10:45
您说的对,您可能在论坛上传了图片,但我是文本AI,无法查看任何上传的图片或附件。请您直接用文字描述 ...

棋子能移动但马乱跳
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 10:46
FishC 发表于 2026-7-5 10:45
您说的对,您可能在论 ...


你说得对,你的马现在仍然可以随意移动,说明之前添加的“马走日”规则没有生效。原因可能是:你只复制了检查的部分,但没有正确嵌入到 `move_piece` 函数中,或者你用的棋子名字与代码中的 `'M'`、`'H'` 不一致。

请**直接替换整个 `move_piece` 函数**为下面的代码(复制覆盖你现有的同名函数)。这段代码已经完整包含马的日字检查、蹩马腿判断,以及其他棋子的基本移动(暂不限制)。替换后马就只能走日字了。

def move_piece(start_idx, end_col, end_row):
    global pieces, turn
    name, col, row, color = pieces
    # ---------- 马的走法检查 ----------
    if name in ('M', 'H'):      # 红马名称为'M',黑马名称为'H'
        dx = end_col - col
        dy = end_row - row
        # 必须满足 |dx| 和 |dy| 其中一个为1另一个为2
        if (abs(dx), abs(dy)) not in :
            return False        # 不是日字,拒绝移动
        # 计算马腿位置
        leg_col = col if abs(dx) == 2 else col + dx // 2   # 横向走2则腿在中间,否则腿的列不变
        leg_row = row + dy // 2 if abs(dy) == 2 else row   # 纵向走2则腿在中间,否则腿的行不变
        # 检查马腿位置是否有棋子
        for n, c, r, clr in pieces:
            if c == leg_col and r == leg_row:
                return False    # 蹩马腿,不能跳
    # ---------- 其他棋子(暂时不限制)----------
    # (后续可以为车、炮等添加规则)
    # ---------- 执行移动(含吃子)----------
    target_idx = None
    for i, (n, c, r, clr) 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        # 不能吃己方棋子
        # 吃掉敌方棋子
        pieces.pop(target_idx)
        # 重新找到自己的索引(因为列表变化)
        for i, (n, c, r, clr) in enumerate(pieces):
            if c == col and r == row and clr == color:
                pieces = (name, end_col, end_row, color)
                break
        return True
    else:
        # 空位直接移动
        pieces = (name, end_col, end_row, color)
        return True

**重要提醒**:
- 请确认你的红马名字是 `'M'`,黑马名字是 `'H'`。如果不同(例如你用了 `'R'` 或 `'B'` 表示马),请修改 `if name in ('M', 'H'):` 中的字母。
- 其他棋子(车、炮、将、士、象)目前仍可以任意移动(因为还没添加它们的规则),这属于正常现象。

替换完成后重新运行,点击马就只能跳到日字位置了。如果依然乱跳,请检查你复制的代码是否完整,以及棋子名字是否匹配。

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

使用道具 举报

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

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

单词是什么意思?main是什么? while running: for event in pygame.event.get():是什么
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 11:10
FishC 发表于 2026-7-5 09:24
请使用这个完全可运行 ...


下面对你代码中的几个单词进行解释:  

1. **`running`**(布尔变量)  
   作用就像电源开关。初始化为 `True`,代表游戏正在运行。当玩家关闭窗口时,`running` 被设为 `False`,主循环结束,程序退出。  

2. **`while running:`**  
   表示“只要 running 为 True,就一直执行下面的缩进代码”。这是 Pygame 游戏的主循环,它会不断更新画面、检测事件并重绘,直到窗口被关闭。  

3. **`for event in pygame.event.get():`**  
   这是一个事件处理循环。`pygame.event.get()` 会返回一个列表,里面包含了当前所有发生的事件(例如鼠标点击、键盘按键、窗口关闭请求等)。`for event in...` 会依次遍历列表中的每个事件,对应处理(比如检测到 `QUIT` 事件就关闭窗口)。  

4. **`main`(函数名)**  
   习惯上定义的一个主函数,用来组织程序的核心流程(初始化、主循环、清理)。在文件末尾通常写 `if __name__ == "__main__": main()`,这样只有当直接运行该文件时才会执行 `main()`,而被导入时不会自动运行。  

如果还有不明白的单词,可以继续问。

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

使用道具 举报

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

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

button是什么?怎么学呢? screen.blit()text1,(MARGIN) BLACK,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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


你提出的问题涉及 pygamen 的基本函数和概念,下面一一解释。  

## 1. `screen.blit()` 是什么?  
`blit` 是“块传输”(Block Transfer)的缩写,作用是把一个表面(Surface)绘制到另一个表面上。在象棋游戏中,你把渲染好的文字(`text1`)放到游戏窗口(`screen`)上。格式是:  

`screen.blit(要绘制的表面, (x坐标, y坐标))`  

例如 `screen.blit(text1, (MARGIN + 1.5 * SIZE, MARGIN + 4 * SIZE))` 就是把“CHU HE”这个文字放在棋盘中间偏左的位置。  

## 2. `BROWN`, `BLACK` 是什么意思?  
这些都是颜色变量。在代码开头你定义了:  

`BROWN = (200, 160, 100)`  
`BLACK = (0, 0, 0)`  

它们都是 RGB 三元组,分别表示棕色和黑色。你可以在 `pygame.draw.line()` 等函数中直接用这些变量指定线条或填充的颜色。  

## 3. `MARGIN` 和 `SIZE` 是什么?  
- `MARGIN`(边距):棋盘离窗口边缘的像素距离,设为 40 像素,所以棋盘不会贴着窗口边界。  
- `SIZE`(格子大小):每个棋盘格子的宽度/高度,设为 60 像素。所以从 `MARGIN` 开始,每增加一列就加 `SIZE` 像素。  

例如 `y = MARGIN + row * SIZE` 计算第 `row` 行横线的纵坐标。  

## 4. `for row in range(10)` 是什么意思?  
`range(10)` 生成从 0 到 9 共 10 个数字。每一轮循环中用变量 `row` 取一个数字(0,1,2...9),用来计算该行横线的 y 坐标。棋盘有 10 条横线,所以循环 10 次。  

## 5. `button` 在哪?  
你目前写的代码中 **没有 button(按钮)**。如果你想要一个“重新开始”或“退出”按钮,需要自己创建。基本做法是:  
- 定义一个矩形区域 `pygame.Rect(x, y, width, height)`  
- 在循环中检测鼠标点击是否落在这个矩形内,然后执行相应功能。  

例如(只加在 main 循环的事件处理中):  

restart_rect = pygame.Rect(500, 650, 100, 40)  
if event.type == pygame.MOUSEBUTTONDOWN:  
    if restart_rect.collidepoint(event.pos):  
        # 重置棋盘  

## 6. 怎么学 pygame?  
推荐步骤:  
- 先理解 **Pygame 官方文档** 的快速入门部分(搜索 “pygame intro”)。  
- 从最简单的例子开始:画一个窗口、画一个圆、检测键盘输入。  
- 尝试写一个 **弹球游戏**(Pong),这样你就能熟悉事件循环、碰撞检测、表面绘制。  
- 然后再回到中国象棋项目,为每种棋子添加规则。  

如果你对某个函数仍感困惑,可以直接问它的详细作用,我会用生活中的例子帮你理解。

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

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层
FishC 发表于 2026-7-5 11:15
你提出的问题涉及 pygamen 的基本函数和概念,下面一一解释。  

## 1. `screen.blit()` 是什么?  
...

恩,bottom,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 11:18
FishC 发表于 2026-7-5 11:15
你提出的问题涉及 pyga ...


你问的 `bottom` 在代码中有两个不同用途,我分开解释:  

## 1. 画竖线时的 `bottom`  
  1. top = MARGIN
  2. bottom = MARGIN + 9 * SIZE
复制代码

这里 `bottom` 存储的是**棋盘最下面那条横线的Y坐标**(即第9行、第10条横线)。  
因为棋盘有10条横线,最上面第0行Y = MARGIN,最下面第9行Y = MARGIN + 9*SIZE。  
当画左右两边的竖线(col==0或col==8)时,从 `top`(第0行)画到 `bottom`(第9行),这样竖线就贯穿整个棋盘。  

## 2. 画九宫斜线时的 `bottom`  
  1. for (left, top) in :
  2.     right = left + 2 * SIZE
  3.     bottom = top + 2 * SIZE
复制代码

这里的 `top` 是九宫左上角Y坐标,`left` 是左上角X坐标。  
`bottom = top + 2*SIZE` 表示九宫右下角的Y坐标。因为九宫是3列×3行,宽和高都是2个格子(边长2*SIZE)。  
所以 `bottom` 是九宫底边的Y坐标,用来和 `right` 配合画矩形对角线。  

简单记:  
- 画棋盘竖线时,`bottom` = 整个棋盘的底边。  
- 画九宫斜线时,`bottom` = 当前九宫小正方形的底边(不是棋盘底边)。  

如果你还有困惑,可以想想:象棋棋盘最下面那条线是棋盘底边,而九宫内部小正方形的底边是中间位置的一条线,两者不同。

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

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层
FishC 发表于 2026-7-5 11:19
你问的 `bottom` 在代码中有两个不同用途,我分开解释:  

## 1. 画竖线时的 `bottom`  

函数生活例子
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 11:21
FishC 发表于 2026-7-5 11:19
你问的 `bottom` 在代 ...


函数就像生活中的**“自动化机器”**:你投进原料(参数),它就自动完成一系列步骤,然后吐出成品(返回值)。我给你三个最贴近的例子:  

**例子1:面包机(极简流程)**  
你放面粉+水+酵母(输入),按开关,面包机自动搅拌、发酵、烘烤,最终给你一条面包(输出)。这就是一个函数:`make_bread(面粉, 水, 酵母)`。  

**例子2:快递驿站(带多个步骤)**  
你去寄快递(调用函数),快递员接收包裹(输入:包裹),扫描、贴单、装车、运输、派送(函数内部代码),最后送到收件人手上(返回值:物流完成)。  

**例子3:点外卖(带参数和返回值)**  
你在外卖APP上点了“宫保鸡丁”(输入参数),餐厅接到订单(函数被调用),厨师按配方做菜(执行代码),打包送出,送到你门口(输出返回值)。  

**函数的本质**:把一堆操作打包成一个“黑盒子”,你只需要知道“给什么”(参数)和“得到什么”(返回值),不用关心盒子里面怎么转。这样代码可以复用,不会重复写同样的步骤。  

如果你还觉得抽象,可以把函数想象成**遥控器上的“一键组合”按钮**:按一下,电视自动完成音量调整、频道切换、输入源选择等一系列动作。

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

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层
FishC 发表于 2026-7-5 11:21
函数就像生活中的**“自动化机器”**:你投进原料(参数),它就自动完成一系列步骤,然后吐出成品(返 ...

把象棋写全,就可以胜利,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层
过默 发表于 2026-07-05 11:24
FishC 发表于 2026-7-5 11:21
函数就像生活中的**“ ...


要实现在吃子后判断胜负(一方的将/帅被吃掉则另一方胜利),你需要做两件事:  

1. **在移动成功后检查棋盘上是否还有红方的将和黑方的帅**  
2. **如果缺少,显示胜利信息并停止游戏**  

## 在现有代码中添加胜负判断

在你的 `handle_click` 函数中,移动成功(`success = True`)之后,立即进行检查。下面是完整的修改方案(直接替换你的 `handle_click` 函数):

def handle_click(mouse_pos):
    global selected_piece, turn, running   # 加入 running 以便结束游戏
    click_col, click_row = get_click_pos(mouse_pos)
   
    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:
        success = move_piece(selected_piece, click_col, click_row)
        if success:
            # ------ 胜负判断 ------
            red_king_exists = any(name == 'K' and color == RED for name, col, row, color in pieces)
            black_king_exists = any(name == 'K' and color == BLACK for name, col, row, color in pieces)
            if not red_king_exists:
                print("黑方胜利!")   # 可在屏幕上显示
                # 以下两行可选:显示文字并关闭窗口
                # draw_victory("BLACK WINS")
                # pygame.time.wait(3000)
                running = False
            elif not black_king_exists:
                print("红方胜利!")
                running = False
            else:
                # 正常切换回合
                turn = 'black' if turn == 'red' else 'red'
        selected_piece = None

**说明**:  
- 假设你的红方将名字是 `'K'`,黑方帅名字也是 `'K'`,但颜色不同。如果名字不同(例如红方为 `'R'`,黑方为 `'B'`),请相应修改条件中的 `name == 'R'` 等。  
- 运行后,一旦一方被吃光将/帅,控制台会输出胜利信息,并且游戏窗口关闭(`running = False`)。  
- 你也可以在屏幕上显示文字(例如用 `font.render` 绘制并 `blit`),这里为了简单只打印到控制台。  

如果你希望在屏幕上显示“红胜”或“黑胜”,可以在主循环的绘制部分加入如下函数:

def draw_victory(text):
    font = pygame.font.Font(None, 60)
    victory_surf = font.render(text, True, (255, 215, 0))  # 金色
    text_rect = victory_surf.get_rect(center=(WIDTH//2, HEIGHT//2))
    screen.blit(victory_surf, text_rect)
    pygame.display.flip()

然后再 main 循环中,当 `running` 为 False 时,调用 `draw_victory` 并等待几秒再退出。示例:

if not running:
    draw_victory("BLACK WINS" if not red_king_exists else "RED WINS")
    pygame.time.wait(3000)
    break

这需要你把胜利判断的结果保存在一个全局变量(如 `winner`)中。但为了简化,可以直接在 `handle_click` 中设置 `running = False`,然后让主循环自然退出。

## 完整胜利流程(推荐)

修改 main 循环为:

def main():
    global running
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
                handle_click(event.pos)
        draw_board()
        draw_pieces()
        pygame.display.flip()
        clock.tick(30)
    # 程序结束前显示胜利画面(如果winner不为空)
    if winner is not None:
        draw_victory(winner)
        pygame.time.wait(3000)
    pygame.quit()
    sys.exit()

这里需要全局变量 `game_over` 和 `winner`。你可以自行添加。不过最简单的办法就是上面那种,在胜利后直接 `running = False` 退出,控制台能看到胜利信息。

如果不想退出,可以设置 `game_over = True` 并在打印后禁用点击,然后显示文字。这需要你调整代码结构。目前先按上述方法执行,吃子后立即结束窗口并打印,你能立刻验证胜利条件是否生效。

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

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层
FishC 发表于 2026-7-5 11:25
要实现在吃子后判断胜负(一方的将/帅被吃掉则另一方胜利),你需要做两件事:  

1. **在移动成功后 ...

学不了,看不懂,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

font = pygame.font.Font("simsunb.ttf", 30)
windows文件简体字体文件名放到python3.8目录了,没显示字
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层
过默 发表于 2026-07-05 11:40
FishC 发表于 2026-7-5 09:00
如何学象棋  
1. 先背 ...


这个问题是字体文件路径不对。pygame的Font函数默认在当前工作目录(也就是运行python脚本的目录)找字体文件。你把“simsunb.ttf”放在Python3.8的安装目录(比如C:\Python38)下,但你的脚本是在另一个目录运行的,所以找不到文件。

正确做法:  
      
  • 把字体文件放在脚本所在的文件夹,然后直接写名字:  
    1. font = pygame.font.Font("simsunb.ttf", 30)
    复制代码
  • 或者写完整路径:  
    1. font = pygame.font.Font("C:/Python38/simsunb.ttf", 30)
    复制代码

  

如果文件确实在脚本同目录下还不行,先检查文件名拼写、后缀是否为小写。也可以先尝试用系统的中文字体,比如:  
  1. font = pygame.font.SysFont("simsun", 30)
复制代码

SysFont可以直接用系统字体名称,不需要文件路径。

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

使用道具 举报

 楼主| 发表于 半小时前 | 显示全部楼层
FishC 发表于 2026-7-5 11:40
这个问题是字体文件路径不对。pygame的Font函数默认在当前工作目录(也就是运行python脚本的目录)找字 ...

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 168, in main
    draw_board()
  File "C:\Program Files\Python38\qipan.py", line 59, in draw_board
    font = pygame.font.Font("simsun", 30)
FileNotFoundError: No file 'simsun' found in working directory 'C:\Program Files\Python38'.
  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 - Full")
  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), ('马', 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), ('C', 1, 2, RED), ('C', 7, 2, RED), ('S', 0, 3, RED),
  19.     ('S', 2, 3, RED), ('S', 4, 3, RED), ('S', 6, 3, RED), ('S', 8, 3, RED),
  20.     ('R', 0, 9, BLACK), ('H', 1, 9, BLACK), ('E', 2, 9, BLACK), ('A', 3, 9, BLACK),
  21.     ('K', 4, 9, BLACK), ('A', 5, 9, BLACK), ('E', 6, 9, BLACK), ('H', 7, 9, BLACK),
  22.     ('R', 8, 9, BLACK), ('C', 1, 7, BLACK), ('C', 7, 7, BLACK), ('S', 0, 6, BLACK),
  23.     ('S', 2, 6, BLACK), ('S', 4, 6, BLACK), ('S', 6, 6, BLACK), ('S', 8, 6, BLACK)
  24. ]

  25. selected_piece = None
  26. turn = 'red'

  27. def draw_board():
  28.     screen.fill(BROWN)
  29.     # 横线
  30.     for row in range(10):
  31.         y = MARGIN + row * SIZE
  32.         pygame.draw.line(screen, BLACK, (MARGIN, y), (MARGIN + 8 * SIZE, y), 2)
  33.     # 竖线
  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.             # 上半
  42.             pygame.draw.line(screen, BLACK, (x, top), (x, top + 4 * SIZE), 2)
  43.             # 下半
  44.             pygame.draw.line(screen, BLACK, (x, top + 5 * SIZE), (x, bottom), 2)
  45.     # 九宫斜线
  46.     for (left, top) in [(MARGIN + 3 * SIZE, MARGIN), (MARGIN + 3 * SIZE, MARGIN),
  47.                         (MARGIN + 3 * SIZE, MARGIN + 7 * SIZE), (MARGIN + 3 * SIZE, MARGIN + 7 * SIZE)]:
  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.Font("simsun", 30)
  54.     text1 = font.render("CHU HE", True, BLACK)
  55.     text2 = font.render("HAN JIE", 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.Font(None, 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 get_click_pos(mouse_pos):
  69.     x, y = mouse_pos
  70.     col = round((x - MARGIN) / SIZE)
  71.     row = round((y - MARGIN) / SIZE)
  72.     if 0 <= col <= 8 and 0 <= row <= 9:
  73.         return col, row
  74.     return None, None

  75. def move_piece(start_idx, end_col, end_row):
  76.     global pieces, turn
  77.     name, col, row, color = pieces[start_idx]
  78.     # 判断目标位置是否有棋子(吃子或空位)
  79.     target_idx = None
  80.     for i, (n, c, r, colr) in enumerate(pieces):
  81.         if c == end_col and r == end_row:
  82.             target_idx = i
  83.             break

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

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

  107.     # ----------------- 执行移动(含吃子) -----------------
  108.     if target_idx is not None:
  109.         target_color = pieces[target_idx][3]
  110.         if target_color != color:  # 吃子
  111.             pieces.pop(target_idx)
  112.             # 重新找到自己的索引(因为列表变动)
  113.             new_idx = None
  114.             for i, (n, c, r, colr) in enumerate(pieces):
  115.                 if c == col and r == row and colr == color:
  116.                     new_idx = i
  117.                     break
  118.             if new_idx is not None:
  119.                 pieces[new_idx] = (name, end_col, end_row, color)
  120.             return True
  121.         else:
  122.             return False  # 不能吃己方棋子
  123.     else:
  124.         # 空位直接移动
  125.         pieces[start_idx] = (name, end_col, end_row, color)
  126.         return True

  127. def handle_click(mouse_pos):
  128.     global selected_piece, turn
  129.     click_col, click_row = get_click_pos(mouse_pos)
  130.     if click_col is None:
  131.         return
  132.     if selected_piece is None:
  133.         # 尝试选中当前回合方的棋子
  134.         for i, (name, col, row, color) in enumerate(pieces):
  135.             if col == click_col and row == click_row:
  136.                 if (turn == 'red' and color == RED) or (turn == 'black' and color == BLACK):
  137.                     selected_piece = i
  138.                 break
  139.     else:
  140.         # 尝试移动
  141.         if move_piece(selected_piece, click_col, click_row):
  142.             # 成功移动,切换回合
  143.             turn = 'black' if turn == 'red' else 'red'
  144.         # 无论移动成功与否,清除选中状态
  145.         selected_piece = None

  146. def main():
  147.     running = True
  148.     while running:
  149.         for event in pygame.event.get():
  150.             if event.type == pygame.QUIT:
  151.                 running = False
  152.             elif event.type == pygame.MOUSEBUTTONDOWN:
  153.                 handle_click(event.pos)
  154.         draw_board()
  155.         draw_pieces()
  156.         pygame.display.flip()
  157.         clock.tick(30)
  158.     pygame.quit()
  159.     sys.exit()

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-5 12:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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