鱼C论坛

 找回密码
 立即注册
查看: 56|回复: 19

python

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式

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

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

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

使用道具 举报

发表于 4 小时前 | 显示全部楼层
中国象棋的Python实现主要分为棋盘表示和棋子移动两大部分。下面是一个简洁易懂的入门框架,你可以在此基础上扩展完整规则。

  • **棋盘表示**:通常用10行9列的二维列表(list),每个元素存储棋子对象或空值(如None)。
  • **棋子类**:每个棋子有颜色、类型、当前位置。类型包括“车、马、象、士、将、炮、兵”。
  • **移动函数**:根据棋子类型,判断目标位置是否合法(走法规则+不能吃己方棋子)。


下面是一个简化的代码示例(仅展示核心结构,未实现所有走法):


  1. class ChessPiece:
  2.     def __init__(self, color, piece_type):
  3.         self.color = color        # 'red' or 'black'
  4.         self.piece_type = piece_type

  5. board = [[None for _ in range(9)] for _ in range(10)]

  6. # 初始化示例(红方车在左下角)
  7. board[9][0] = ChessPiece('red', 'rook')

  8. def move_piece(from_row, from_col, to_row, to_col):
  9.     piece = board[from_row][from_col]
  10.     if piece is None:
  11.         return False
  12.     # 检查目标位置是否合法(此处以“车”为例:只能直线移动)
  13.     if piece.piece_type == 'rook':
  14.         if from_row == to_row:  # 横向移动
  15.             step = 1 if to_col > from_col else -1
  16.             for col in range(from_col + step, to_col, step):
  17.                 if board[from_row][col] is not None:
  18.                     return False  # 有阻挡
  19.         elif from_col == to_col:  # 纵向移动
  20.             step = 1 if to_row > from_row else -1
  21.             for row in range(from_row + step, to_row, step):
  22.                 if board[row][from_col] is not None:
  23.                     return False
  24.         else:
  25.             return False  # 不沿直线,非法
  26.         # 不能吃己方棋子
  27.         target = board[to_row][to_col]
  28.         if target is not None and target.color == piece.color:
  29.             return False
  30.         # 执行移动
  31.         board[to_row][to_col] = piece
  32.         board[from_row][from_col] = None
  33.         return True
  34.     # 其他棋子走法类似,需要分别实现
  35.     return False
复制代码


如果你希望有图形界面,可以使用pygametkinter绘制棋盘和棋子,但核心逻辑与上述相同。记住,完整的象棋程序需要为每种棋子(车、马、象、士、将、炮、兵)实现各自的移动规则和特殊限制(如马脚、象眼、炮架、老将对面等)。

建议从控制台版本开始练习,逐步添加规则判断。

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:13
中国象棋的Python实现主要分为棋盘表示和棋子移动两大部分。下面是一个简洁易懂的入门框架,你可以在此基础 ...

**棋盘表示**:通常用10行9列的二维列表(list),每个元素存储棋子对象或空值(如None)。
怎么使用pygame或tkinter绘制棋盘棋子?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:15
FishC 发表于 2026-7-15 08:13
中国象棋的Python实现 ...


使用 pygametkinter 绘制中国象棋棋盘和棋子,本质是两步:画出 9×10 的网格线,然后在交点贴上棋子(圆形或图片)。下面给出两种方案的核心思路和精简代码(仅展示绘图部分,不含游戏逻辑)。

---

**一、用 tkinter 绘制(无需额外安装)**

**1. 创建画布,设置坐标**

棋盘每个格子宽高设为 SIZE = 60 像素,棋子半径为 R = 25。左上角起始点 (padding, padding)。

**2. 画竖线和横线(注意河界留空)**


  1. import tkinter as tk

  2. root = tk.Tk()
  3. canvas = tk.Canvas(root, width=700, height=750, bg='white')
  4. canvas.pack()

  5. SIZE = 60
  6. R = 25
  7. padding = 30

  8. # 画横线:10行(0-9)
  9. for row in range(10):
  10.     y = padding + row * SIZE
  11.     canvas.create_line(padding, y, padding + 8*SIZE, y, width=2)

  12. # 画竖线:9列(0-8),但中间河界(第4、5行之间)不画竖线
  13. for col in range(9):
  14.     x = padding + col * SIZE
  15.     # 上半棋盘(行0-4)
  16.     canvas.create_line(x, padding, x, padding + 4*SIZE, width=2)
  17.     # 下半棋盘(行5-9)
  18.     canvas.create_line(x, padding + 5*SIZE, x, padding + 9*SIZE, width=2)

  19. # 画交叉点装饰(可选)
  20. for row in range(10):
  21.     for col in range(9):
  22.         cx = padding + col * SIZE
  23.         cy = padding + row * SIZE
  24.         # 在边框线端点添加小圆点(仅内部交叉点可省略)
  25.         if (col==0 or col==8) and (row==0 or row==9):
  26.             canvas.create_oval(cx-3, cy-3, cx+3, cy+3, fill='black')
  27. root.mainloop()
复制代码


**3. 画棋子**


  1. # 在 (col, row) 处画一个红方“车”
  2. def draw_piece(canvas, col, row, color, text):
  3.     x = padding + col * SIZE
  4.     y = padding + row * SIZE
  5.     canvas.create_oval(x-R, y-R, x+R, y+R, fill=color, outline='black', width=2)
  6.     canvas.create_text(x, y, text=text, font=('Arial', 20, 'bold'), fill='white' if color=='red' else 'black')

  7. # 示例:红车在(0,9)位置
  8. draw_piece(canvas, 0, 9, 'red', '车')
  9. root.mainloop()
复制代码


---

**二、用 pygame 绘制(更灵活、适合游戏循环)**

**1. 初始化并定义颜色**


  1. import pygame
  2. pygame.init()
  3. SIZE = 60
  4. R = 25
  5. WIDTH = 700
  6. HEIGHT = 750
  7. screen = pygame.display.set_mode((WIDTH, HEIGHT))
  8. pygame.display.set_caption('中国象棋')
复制代码


**2. 绘制棋盘(先画背景色,再画线)**


  1. screen.fill((220, 180, 140))  # 木色背景
  2. padding = 30

  3. # 画横线
  4. for row in range(10):
  5.     start = (padding, padding + row * SIZE)
  6.     end = (padding + 8 * SIZE, padding + row * SIZE)
  7.     pygame.draw.line(screen, (0,0,0), start, end, 2)

  8. # 画竖线(分上下半棋盘)
  9. for col in range(9):
  10.     x = padding + col * SIZE
  11.     top_start = (x, padding)
  12.     top_end = (x, padding + 4 * SIZE)
  13.     bot_start = (x, padding + 5 * SIZE)
  14.     bot_end = (x, padding + 9 * SIZE)
  15.     pygame.draw.line(screen, (0,0,0), top_start, top_end, 2)
  16.     pygame.draw.line(screen, (0,0,0), bot_start, bot_end, 2)

  17. # 添加交叉点装饰(可选,用圆点)
  18. for row in range(10):
  19.     for col in range(9):
  20.         if (col==0 or col==8) and (row==0 or row==9):
  21.             cx = padding + col * SIZE
  22.             cy = padding + row * SIZE
  23.             pygame.draw.circle(screen, (0,0,0), (cx, cy), 3)
  24. pygame.display.flip()
复制代码


**3. 画棋子函数**


  1. def draw_piece(screen, col, row, color, text, font):
  2.     x = padding + col * SIZE
  3.     y = padding + row * SIZE
  4.     pygame.draw.circle(screen, (0,0,0), (x, y), R, 2)  # 边框
  5.     pygame.draw.circle(screen, color, (x, y), R-2)     # 填充
  6.     text_surface = font.render(text, True, (0,0,0))
  7.     text_rect = text_surface.get_rect(center=(x, y))
  8.     screen.blit(text_surface, text_rect)

  9. font = pygame.font.SysFont('simhei', 24)
  10. draw_piece(screen, 0, 9, (200,50,50), '车', font)
  11. pygame.display.flip()
复制代码


---

**要点总结**:  
- tkinter 适合静态应用和简单交互,pygame 更适合游戏循环、实时动画。  
- 棋子坐标(col, row)对应 0≤col≤8,0≤row≤9。  
- 绘制时注意“河界”(第4、5行之间)不画竖线,只保留边框。  
- 棋子颜色建议红方用红色圆、黑方用黑色圆,文字用对比色。

你可以复制上述代码运行查看效果,再结合之前给出的棋子移动逻辑,即可做出一个简易象棋程序。动手试试吧!

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:15
使用 pygame 或 tkinter 绘制中国象棋棋盘和棋子,本质是两步:画出 9×10 的网格线,然后在交点贴上棋 ...

# 示例:红车在(0,9)位置
draw_piece(canvas, 0, 9, 'red', '车')
draw_piece(canvas,0, 7,'red','马')
马位置不对
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:24
FishC 发表于 2026-7-15 08:15
使用 pygame 或 tkint ...


抱歉,我给的示例代码中 `draw_piece(canvas, 0, 7, 'red', '马')` 确实不是象棋的标准初始位置。标准红方马应在 **(1, 9)** 和 **(7, 9)** 两处,黑方马则在 **(1, 0)** 和 **(7, 0)**。

代码中的坐标参数 `(col, row)` 遵循:
- **col**(列): 0(最左边)到 8(最右边)
- **row**(行): 0(最上边,黑方底线)到 9(最下边,红方底线)

如果你想初始化一个标准布局,可以这样写:

  1. # 红方(row=9 为底线)
  2. draw_piece(canvas, 0, 9, 'red', '车')   # 左车
  3. draw_piece(canvas, 1, 9, 'red', '马')   # 左马(正确位置)
  4. draw_piece(canvas, 2, 9, 'red', '象')   # 左相
  5. draw_piece(canvas, 3, 9, 'red', '士')   # 左士
  6. draw_piece(canvas, 4, 9, 'red', '将')   # 帅
  7. draw_piece(canvas, 5, 9, 'red', '士')   # 右士
  8. draw_piece(canvas, 6, 9, 'red', '象')   # 右相
  9. draw_piece(canvas, 7, 9, 'red', '马')   # 右马
  10. draw_piece(canvas, 8, 9, 'red', '车')   # 右车
  11. draw_piece(canvas, 1, 7, 'red', '炮')   # 左炮
  12. draw_piece(canvas, 7, 7, 'red', '炮')   # 右炮
  13. for col in range(0, 9, 2):             # 兵在 (0,6), (2,6), (4,6), (6,6), (8,6)
  14.     draw_piece(canvas, col, 6, 'red', '兵')

  15. # 黑方(row=0 为底线)
  16. draw_piece(canvas, 0, 0, 'black', '車')
  17. draw_piece(canvas, 1, 0, 'black', '馬')
  18. draw_piece(canvas, 2, 0, 'black', '象')
  19. draw_piece(canvas, 3, 0, 'black', '士')
  20. draw_piece(canvas, 4, 0, 'black', '将')
  21. draw_piece(canvas, 5, 0, 'black', '士')
  22. draw_piece(canvas, 6, 0, 'black', '象')
  23. draw_piece(canvas, 7, 0, 'black', '馬')
  24. draw_piece(canvas, 8, 0, 'black', '車')
  25. draw_piece(canvas, 1, 2, 'black', '炮')
  26. draw_piece(canvas, 7, 2, 'black', '炮')
  27. for col in range(0, 9, 2):
  28.     draw_piece(canvas, col, 3, 'black', '卒')
复制代码


注意:棋盘最下面一行(row=9)是红方,最上面一行(row=0)是黑方。按照这个布局运行,就能看到标准的象棋开局画面了。

感谢你的细心指出,祝你编程愉快!

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:25
抱歉,我给的示例代码中 `draw_piece(canvas, 0, 7, 'red', '马')` 确实不是象棋的标准初始位置。标准 ...


# 黑方(row=0 为底线)
draw_piece(canvas, 0, 0, 'black', '車')
draw_piece(canvas, 1, 0, 'black', '馬')
draw_piece(canvas, 2, 0, 'black', '象')
draw_piece(canvas, 3, 0, 'black', '士')
draw_piece(canvas, 4, 0, 'black', '将')
draw_piece(canvas, 5, 0, 'black', '士')
draw_piece(canvas, 6, 0, 'black', '象')
draw_piece(canvas, 7, 0, 'black', '馬')
draw_piece(canvas, 8, 0, 'black', '車')
draw_piece(canvas, 1, 2, 'black', '炮')
draw_piece(canvas, 7, 2, 'black', '炮')
for col in range(0, 9, 2):
    draw_piece(canvas, col, 3, 'black', '卒')

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

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:27
FishC 发表于 2026-7-15 08:25
抱歉,我给的示例代码 ...


你说得对,“黑没字”是因为黑方棋子文字的颜色与背景相同,导致看不见。在之前给出的 `draw_piece` 函数中,文字颜色是这样设置的:

  1. canvas.create_text(x, y, text=text, font=('Arial', 20, 'bold'), fill='white' if color=='red' else 'black')
复制代码


当 `color` 为 `'red'` 时文字白色,在红色圆上看得见;但 `color` 为 `'black'` 时文字黑色,而圆背景也是黑色,于是文字完全消失。

**修正方法**:无论红方还是黑方,文字颜色都设为白色(或浅色)。修改后:

  1. canvas.create_text(x, y, text=text, font=('Arial', 20, 'bold'), fill='white')
复制代码


完整修正的 `draw_piece` 函数:

  1. def draw_piece(canvas, col, row, color, text):
  2.     x = padding + col * SIZE
  3.     y = padding + row * SIZE
  4.     # 画黑色边框
  5.     canvas.create_oval(x-R, y-R, x+R, y+R, outline='black', width=2)
  6.     # 画填充色(红或黑)
  7.     canvas.create_oval(x-R, y-R, x+R, y+R, fill=color)
  8.     # 文字始终用白色
  9.     canvas.create_text(x, y, text=text, font=('Arial', 20, 'bold'), fill='white')
复制代码


这样黑方棋子上的“車、馬、象……”就能清晰显示白色文字了。如果仍显示乱码(方块),请确保系统支持中文字体,可将 `font` 改为 `('SimHei', 20, 'bold')` 等中文字体名称。

另外,建议将红黑两色用明度较高的红色(如 `'#CC0000'`)和黑色,文字白色对比度最佳。快去试试修改后的代码吧!

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:27
你说得对,“黑没字”是因为黑方棋子文字的颜色与背景相同,导致看不见。在之前给出的 `draw_piece` 函 ...

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

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:29
FishC 发表于 2026-7-15 08:27
你说得对,“黑没字” ...


以下是针对“棋子移动”和“人机对战”的简易实现思路,搭配 `pygame` 或 `tkinter` 均可。代码示例以 `pygame` 为例,你可以直接套用之前的绘图框架。

---

## 一、棋子移动:鼠标点击交互

### 1. 坐标映射(棋盘格 → 像素)
假设已定义 `padding`(起始偏移)和 `SIZE`(格子边长),点击像素 `(px, py)` 转棋盘行列:


  1. def pos_to_board(px, py):
  2.     col = round((px - padding) / SIZE)
  3.     row = round((py - padding) / SIZE)
  4.     if 0 <= col <= 8 and 0 <= row <= 9:
  5.         return col, row
  6.     return None
复制代码


### 2. 选中与移动流程
- **选中阶段**:记录玩家点击的格子坐标,若该格有己方棋子,则高亮并进入移动阶段。
- **移动阶段**:玩家再点击一个格子,程序调用 `is_legal_move(piece, from_pos, to_pos)` 判断是否合法。合法则执行移动并切换走棋方。


  1. selected = None  # (col, row)
  2. turn = 'red'     # 当前走棋方

  3. while running:
  4.     for event in pygame.event.get():
  5.         if event.type == pygame.MOUSEBUTTONDOWN:
  6.             pos = pos_to_board(*event.pos)
  7.             if pos is None:
  8.                 continue
  9.             if selected is None:
  10.                 # 检查该格是否有己方棋子
  11.                 piece = board[pos[1]][pos[0]]
  12.                 if piece and piece.color == turn:
  13.                     selected = pos
  14.             else:
  15.                 # 尝试移动
  16.                 from_pos = selected
  17.                 to_pos = pos
  18.                 piece = board[from_pos[1]][from_pos[0]]
  19.                 if is_legal_move(piece, from_pos, to_pos):
  20.                     # 执行移动
  21.                     board[to_pos[1]][to_pos[0]] = piece
  22.                     board[from_pos[1]][from_pos[0]] = None
  23.                     # 切换走棋方
  24.                     turn = 'black' if turn == 'red' else 'red'
  25.                 selected = None  # 清除选中
复制代码


### 3. 合法走法判断(示例:车、马)
你需要为每种棋子实现规则函数。下面给出车的走法(无阻挡)和马的走法(无蹩脚):


  1. def is_legal_move(piece, from_pos, to_pos):
  2.     fx, fy = from_pos
  3.     tx, ty = to_pos
  4.     if fx == tx and fy == ty:
  5.         return False
  6.     # 不能吃己方棋子
  7.     target = board[ty][tx]
  8.     if target and target.color == piece.color:
  9.         return False

  10.     if piece.piece_type == 'rook':  # 车
  11.         if fx != tx and fy != ty:
  12.             return False
  13.         step_col = (tx - fx) // abs(tx - fx) if fx != tx else 0
  14.         step_row = (ty - fy) // abs(ty - fy) if fy != ty else 0
  15.         cx, cy = fx + step_col, fy + step_row
  16.         while (cx, cy) != (tx, ty):
  17.             if board[cy][cx] is not None:
  18.                 return False
  19.             cx += step_col
  20.             cy += step_row
  21.         return True

  22.     if piece.piece_type == 'knight':  # 马
  23.         dx, dy = tx - fx, ty - fy
  24.         if (abs(dx), abs(dy)) not in [(1,2), (2,1)]:
  25.             return False
  26.         # 蹩脚检查
  27.         if abs(dx) == 2:
  28.             leg = (fx + dx//2, fy)
  29.         else:
  30.             leg = (fx, fy + dy//2)
  31.         if board[leg[1]][leg[0]] is not None:
  32.             return False
  33.         return True
  34.     # 其他棋子类似……
  35.     return False
复制代码


---

## 二、人机对战:简单AI

### 1. 随机走法(最易实现)
让计算机从所有己方棋子中随机选一个,再从该棋子的所有合法走法中随机选一个。


  1. import random

  2. def computer_move(board, color):
  3.     pieces = []
  4.     for row in range(10):
  5.         for col in range(9):
  6.             if board[row][col] and board[row][col].color == color:
  7.                 pieces.append((col, row))
  8.     random.shuffle(pieces)
  9.     for col, row in pieces:
  10.         piece = board[row][col]
  11.         # 生成所有合法目标格(这里用暴力遍历全盘)
  12.         candidates = []
  13.         for tcol in range(9):
  14.             for trow in range(10):
  15.                 if is_legal_move(piece, (col,row), (tcol,trow)):
  16.                     candidates.append((tcol, trow))
  17.         if candidates:
  18.             target = random.choice(candidates)
  19.             return (col, row), target
  20.     return None
复制代码


在主循环中,一旦检测到 `turn` 为电脑方,就调用 `computer_move` 并执行移动。注意加上延时,让玩家看到电脑的选择。

### 2. 简单贪心走法(吃子优先)
在 `candidates` 中优先选择能吃掉对方棋子的格子。


  1. def computer_move(board, color):
  2.     pieces = ...  # 同上
  3.     best_move = None
  4.     for col, row in pieces:
  5.         piece = board[row][col]
  6.         for tcol in range(9):
  7.             for trow in range(10):
  8.                 if is_legal_move(piece, (col,row), (tcol,trow)):
  9.                     target = board[trow][tcol]
  10.                     # 如果目标有对方棋子,则优先选择
  11.                     if target and target.color != color:
  12.                         return (col,row), (tcol,trow)  # 立即返回吃子走法
  13.                     # 否则记录一个普通走法
  14.                     if best_move is None:
  15.                         best_move = ((col,row), (tcol,trow))
  16.     return best_move  # 没有吃子就走第一个合法走法
复制代码


### 3. 更进一步的思路(可选)
- **走法评估函数**:给每种棋子赋值(将=1000, 车=9, 马=4, 炮=4.5, …),然后选择己方棋子价值总和最大的走法。
- **极小极大搜索**:一至两层搜索即可,配合Alpha-Beta剪枝。但对初学者较复杂,建议先从贪心开始。

---

## 三、完整运行框架(pygame)

将以上代码整合进之前绘图的 `while` 循环中,注意在电脑走棋前加一小段延时 pygame.time.delay(500) 让玩家看到思考过程。每次移动后重绘棋盘棋子并调用 pygame.display.flip()

**注意**:`board` 推荐使用二维列表,每个格子存储 ChessPiece 对象或 `None`。`ChessPiece` 类可简单定义为:


  1. class ChessPiece:
  2.     def __init__(self, color, piece_type):
  3.         self.color = color
  4.         self.piece_type = piece_type
复制代码


---

开始动手时,不必一次性实现所有棋子的规则。先只让车、马、兵可以移动,再逐步添加。祝你编程顺利,下出自己的象棋AI!

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:29
以下是针对“棋子移动”和“人机对战”的简易实现思路,搭配 `pygame` 或 `tkinter` 均可。代码示例以  ...

Traceback (most recent call last):
  File "C:/Program Files/Python38/hueizhi.py", line 87, in <module>
    while running:
NameError: name 'running' is not defined
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:32
FishC 发表于 2026-7-15 08:29
以下是针对“棋子移动 ...


你的代码报错是因为没有定义 `running` 变量。通常在 Pygame 主循环前要初始化这个变量,比如:

running = True

之后在循环体内可以设置退出条件。下面是一个完整的 Pygame 主循环骨架,包含鼠标点击获取棋盘坐标的逻辑,你可以参照补全:

import pygame
import sys

pygame.init()
screen = pygame.display.set_mode((700, 750))
pygame.display.set_caption('中国象棋')

# 定义常量(请与我之前代码一致)
SIZE = 60
R = 25
padding = 30

# 主循环开关
running = True
selected_piece = None   # 选中的棋子对象(行、列、棋子信息)

# ---------- 定义你的棋盘数据 board 和棋子类等 ----------
# 这里省略,用你之前写的 board 列表和 draw_board 等函数

clock = pygame.time.Clock()

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            # 获取鼠标点击位置
            px, py = event.pos
            col = round((px - padding) / SIZE)
            row = round((py - padding) / SIZE)
            # 检查是否在棋盘范围内
            if 0 <= col <= 8 and 0 <= row <= 9:
                # 处理选子或走子逻辑(调用你之前写的移动函数)
                # 例如:如果 selected_piece 为空,则选中当前位置的棋子;否则尝试走子
                pass

    # 绘制棋盘和棋子(你的绘图函数)
    # draw_board(screen)   # 画网格线
    # for each piece in board: draw_piece(screen, ...)

    pygame.display.flip()
    clock.tick(30)

pygame.quit()
sys.exit()

请务必在 `while running` 之前添加 `running = True`,错误即可解决。如果还有其他未定义变量(如 `board`、`draw_board` 等),需要根据你的代码一并补全。动手试一下吧!

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:32
你的代码报错是因为没有定义 `running` 变量。通常在 Pygame 主循环前要初始化这个变量,比如:

run ...

  1. import tkinter as tk

  2. root = tk.Tk()
  3. canvas = tk.Canvas(root, width=700, height=750, bg='white')
  4. canvas.pack()

  5. SIZE = 60
  6. R = 25
  7. padding = 30

  8. # 画横线:10行(0-9)
  9. for row in range(10):
  10.     y = padding + row * SIZE
  11.     canvas.create_line(padding, y, padding + 8*SIZE, y, width=2)

  12. # 画竖线:9列(0-8),但中间河界(第4、5行之间)不画竖线
  13. for col in range(9):
  14.     x = padding + col * SIZE
  15.     # 上半棋盘(行0-4)
  16.     canvas.create_line(x, padding, x, padding + 4*SIZE, width=2)
  17.     # 下半棋盘(行5-9)
  18.     canvas.create_line(x, padding + 5*SIZE, x, padding + 9*SIZE, width=2)

  19. # 画交叉点装饰(可选)
  20. for row in range(10):
  21.     for col in range(9):
  22.         cx = padding + col * SIZE
  23.         cy = padding + row * SIZE
  24.         # 在边框线端点添加小圆点(仅内部交叉点可省略)
  25.         if (col==0 or col==8) and (row==0 or row==9):
  26.             canvas.create_oval(cx-3, cy-3, cx+3, cy+3, fill='black')

  27. # 在 (col, row) 处画一个红方“车”
  28. def draw_piece(canvas, col, row, color, text):
  29.     x = padding + col * SIZE
  30.     y = padding + row * SIZE
  31.     # 画黑色边框
  32.     canvas.create_oval(x-R, y-R, x+R, y+R, outline='black', width=2)
  33.     # 画填充色(红或黑)
  34.     canvas.create_oval(x-R, y-R, x+R, y+R, fill=color)
  35.     # 文字始终用白色
  36.     canvas.create_text(x, y, text=text, font=('Arial', 20, 'bold'), fill='white')

  37. # 红方(row=9 为底线)
  38. draw_piece(canvas, 0, 9, 'red', '车')   # 左车
  39. draw_piece(canvas, 1, 9, 'red', '马')   # 左马(正确位置)
  40. draw_piece(canvas, 2, 9, 'red', '象')   # 左相
  41. draw_piece(canvas, 3, 9, 'red', '士')   # 左士
  42. draw_piece(canvas, 4, 9, 'red', '将')   # 帅
  43. draw_piece(canvas, 5, 9, 'red', '士')   # 右士
  44. draw_piece(canvas, 6, 9, 'red', '象')   # 右相
  45. draw_piece(canvas, 7, 9, 'red', '马')   # 右马
  46. draw_piece(canvas, 8, 9, 'red', '车')   # 右车
  47. draw_piece(canvas, 1, 7, 'red', '炮')   # 左炮
  48. draw_piece(canvas, 7, 7, 'red', '炮')   # 右炮
  49. for col in range(0, 9, 2):             # 兵在 (0,6), (2,6), (4,6), (6,6), (8,6)
  50.     draw_piece(canvas, col, 6, 'red', '兵')

  51. # 黑方(row=0 为底线)
  52. draw_piece(canvas, 0, 0, 'black', '車')
  53. draw_piece(canvas, 1, 0, 'black', '馬')
  54. draw_piece(canvas, 2, 0, 'black', '象')
  55. draw_piece(canvas, 3, 0, 'black', '士')
  56. draw_piece(canvas, 4, 0, 'black', '将')
  57. draw_piece(canvas, 5, 0, 'black', '士')
  58. draw_piece(canvas, 6, 0, 'black', '象')
  59. draw_piece(canvas, 7, 0, 'black', '馬')
  60. draw_piece(canvas, 8, 0, 'black', '車')
  61. draw_piece(canvas, 1, 2, 'black', '炮')
  62. draw_piece(canvas, 7, 2, 'black', '炮')
  63. for col in range(0, 9, 2):
  64.     draw_piece(canvas, col, 3, 'black', '卒')


  65. def pos_to_board(px, py):
  66.     col = round((px - padding) / SIZE)
  67.     row = round((py - padding) / SIZE)
  68.     if 0 <= col <= 8 and 0 <= row <= 9:
  69.         return col, row
  70.     return None


  71. selected = None  # (col, row)
  72. turn = 'red'     # 当前走棋方

  73. while running:
  74.     for event in pygame.event.get():
  75.         if event.type == pygame.MOUSEBUTTONDOWN:
  76.             pos = pos_to_board(*event.pos)
  77.             if pos is None:
  78.                 continue
  79.             if selected is None:
  80.                 # 检查该格是否有己方棋子
  81.                 piece = board[pos[1]][pos[0]]
  82.                 if piece and piece.color == turn:
  83.                     selected = pos
  84.             else:
  85.                 # 尝试移动
  86.                 from_pos = selected
  87.                 to_pos = pos
  88.                 piece = board[from_pos[1]][from_pos[0]]
  89.                 if is_legal_move(piece, from_pos, to_pos):
  90.                     # 执行移动
  91.                     board[to_pos[1]][to_pos[0]] = piece
  92.                     board[from_pos[1]][from_pos[0]] = None
  93.                     # 切换走棋方
  94.                     turn = 'black' if turn == 'red' else 'red'
  95.                 selected = None  # 清除选中
  96. running = True
  97. root.mainloop()
复制代码

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

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:34
FishC 发表于 2026-7-15 08:32
你的代码报错是因为没 ...


首先恭喜你已经用 `tkinter` 画出了棋盘和棋子。要实现“棋子移动”和“人机对战”,需要做三件事:

1. **用数据结构存储棋盘**:一个二维列表,记录每个交叉点上的棋子(颜色、类型)。  
2. **鼠标点击交互**:点击选中棋子,再次点击目标位置进行移动。  
3. **AI (人机对战)**:最简单的办法是让电脑随机选择一个合法走法。

下面提供可直接追加到你现有代码中的实现。请将你前面的全部代码复制,然后在最后(`root.mainloop()` 之前)添加下面的内容。

---

## 1. 棋盘数据结构(替换你目前的绘制,改为动态更新)

首先定义一个 `board` 列表,`board[row][col]` 存储 `None` 或一个字典 `{'color':'red'/'black', 'type':'车'/'马'/...}`。同时写一个函数 `redraw_all()` 根据 `board` 重绘所有棋子。

在你原来的画线代码之后、画棋子之前,加入:


# ---------- 棋盘数据结构 ----------
board = [ [None]*9 for _ in range(10) ]   # 10行9列

# 棋子初始模板(与你的 draw_piece 参数一致)
init_red = [(0,9,'车'),(1,9,'马'),(2,9,'象'),(3,9,'士'),(4,9,'将'),
            (5,9,'士'),(6,9,'象'),(7,9,'马'),(8,9,'车'),
            (1,7,'炮'),(7,7,'炮')]
for col in range(0,9,2):
    init_red.append((col,6,'兵'))

init_black = [(0,0,'車'),(1,0,'馬'),(2,0,'象'),(3,0,'士'),(4,0,'将'),
              (5,0,'士'),(6,0,'象'),(7,0,'馬'),(8,0,'車'),
              (1,2,'炮'),(7,2,'炮')]
for col in range(0,9,2):
    init_black.append((col,3,'卒'))

for col, row, piece_type in init_red:
    board[row][col] = {'color':'red', 'type':piece_type}
for col, row, piece_type in init_black:
    board[row][col] = {'color':'black', 'type':piece_type}

# 重绘所有棋子(清除旧图并重新画)
def redraw_all():
    canvas.delete('piece')   # 删除所有标签为'piece'的图形
    for row in range(10):
        for col in range(9):
            piece = board[row][col]
            if piece:
                color = 'red' if piece['color']=='red' else 'black'
                text = piece['type']
                draw_piece(canvas, col, row, color, text, tag='piece')

# 修改 draw_piece 函数,增加一个 tag 参数以便删除
def draw_piece(canvas, col, row, color, text, tag=None):
    x = padding + col * SIZE
    y = padding + row * SIZE
    canvas.create_oval(x-R, y-R, x+R, y+R, outline='black', width=2, tags=tag)
    canvas.create_oval(x-R, y-R, x+R, y+R, fill=color, tags=tag)
    canvas.create_text(x, y, text=text, font=('Arial', 20, 'bold'), fill='white', tags=tag)

# 调用一次重绘,替代下面原来的一大串 draw_piece 调用
redraw_all()


(注释:请删除你原来所有 `draw_piece` 的调用,只保留 `redraw_all()` 即可。)

---

## 2. 鼠标点击处理(选棋+移动)

在 `redraw_all` 之后、`root.mainloop()` 之前,添加:


selected = None   # 存储 (row, col) 选中的棋子

def on_click(event):
    global selected
    px, py = event.x, event.y
    col = round((px - padding) / SIZE)
    row = round((py - padding) / SIZE)
    if not (0 <= col <= 8 and 0 <= row <= 9):
        return

    # 如果没有选中任何棋子
    if selected is None:
        # 检查该位置是否有棋子,且是红方(或根据玩家颜色)
        piece = board[row][col]
        if piece and piece['color'] == 'red':   # 假设玩家执红
            selected = (row, col)
            # 可以给选中棋子加个高亮(简单起见不做了)
    else:
        # 已经选中了一个棋子,准备移动
        from_row, from_col = selected
        to_row, to_col = row, col
        # 简单的移动:仅检查是否在棋盘内、目标是否为空或敌方(不验证走法规则)
        if (from_row, from_col) == (to_row, to_col):
            selected = None   # 点击同一位置取消选中
            return
        # 检查目标是否是己方棋子
        target = board[to_row][to_col]
        if target and target['color'] == 'red':
            selected = (to_row, to_col)   # 重新选中
            return
        # 执行移动(不考虑规则,只演示)
        board[to_row][to_col] = board[from_row][from_col]
        board[from_row][from_col] = None
        selected = None
        # 重绘
        redraw_all()
        # 移动后轮到电脑(黑方),启动电脑走棋
        root.after(500, computer_move)   # 延迟0.5秒让玩家看到局面

canvas.bind('<Button-1>', on_click)


---

## 3. 简单的人机对战(电脑随机走合法步)

最简单的 AI 是列举所有黑方棋子的所有可能走法(不考虑规则),随机选择一个。这里只演示“移动到空位或吃红方”但不检查走法规则,真实规则代码较长,你可以逐步完善。


import random

def computer_move():
    # 收集所有黑方棋子
    black_pieces = []
    for r in range(10):
        for c in range(9):
            p = board[r][c]
            if p and p['color'] == 'black':
                black_pieces.append((r, c))
    # 寻找所有合法目标(不考虑走法规则,只允许移动到空位或红方)
    moves = []
    for r, c in black_pieces:
        # 简单:尝试周围八个方向(实际应依棋子类型)
        # 这里仅演示移动到相邻四个方向(上下左右)
        for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
            nr, nc = r+dr, c+dc
            if 0 <= nr <= 9 and 0 <= nc <= 8:
                target = board[nr][nc]
                if target is None or target['color'] == 'red':
                    moves.append((r, c, nr, nc))
        # 还可以加入对角线(象走日等,但此处省略)
    if moves:
        fr, fc, tr, tc = random.choice(moves)
        board[tr][tc] = board[fr][fc]
        board[fr][fc] = None
        redraw_all()
    # 若无可行移动,则玩家胜,但这里不处理


最后启动 tkinter 主循环:

root.mainloop()


---

**完整运行流程**  
- 运行后显示标准开局。  
- 点击红方棋子(选中),再点击一个空位或黑方棋子,红方移动(无规则检查)。  
- 移动后黑方自动随机走一步(约0.5秒后)。  
- 周而复始。  

你可以在此基础上逐步添加上“马脚”“蹩马腿”“炮隔子打”“将帅对面”等真实规则,并将电脑 AI 改为更智能的搜索算法(如极小化极大搜索)。  

动手试试吧!如果还有问题,请贴出具体报错内容。

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
Traceback (most recent call last):
  File "C:/Program Files/Python38/hueizhi.py", line 88, in <module>
    for event in pygame.event.get():
NameError: name 'pygame' is not defined
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:43
Traceback (most recent call last):
  File "C:/Pro ...


看起来你混淆了两个库:你当前的代码是基于 `tkinter` 的,但错误信息显示你试图运行 `pygame` 的代码(`pygame.event.get()`)。这两个库不能混用。

请检查你在 `hueizhi.py` 中到底用了哪一套代码。如果你确实是用 `tkinter` 画棋盘(就像上一段你贴出的完整代码那样),那么你只需要继续用 `tkinter` 的交互方式,不要导入 `pygame`。

下面我专门针对你这段 **tkinter 代码**,提供完整的棋子移动和人机对战实现。你只需将以下内容追加到你的 `hueizhi.py` 末尾(`root.mainloop()` 之前)即可。

**首先,在你原来的代码中找到最后一行 `root.mainloop()`,把它注释掉或删除,然后替换为下面的完整程序。**(当然你也可以在之前插入,但要确保数据结构定义好。)

---

### 完整 tkinter 人机对战代码(可直接替换你的文件末尾)

  1. import tkinter as tk
  2. import random

  3. root = tk.Tk()
  4. root.title('中国象棋 - 人机对战')
  5. canvas = tk.Canvas(root, width=700, height=750, bg='white')
  6. canvas.pack()

  7. SIZE = 60
  8. R = 25
  9. padding = 30

  10. # ----- 画棋盘(你的原代码)-----
  11. for row in range(10):
  12.     y = padding + row * SIZE
  13.     canvas.create_line(padding, y, padding + 8*SIZE, y, width=2)
  14. for col in range(9):
  15.     x = padding + col * SIZE
  16.     canvas.create_line(x, padding, x, padding + 4*SIZE, width=2)
  17.     canvas.create_line(x, padding + 5*SIZE, x, padding + 9*SIZE, width=2)
  18. for row in range(10):
  19.     for col in range(9):
  20.         cx = padding + col * SIZE
  21.         cy = padding + row * SIZE
  22.         if (col==0 or col==8) and (row==0 or row==9):
  23.             canvas.create_oval(cx-3, cy-3, cx+3, cy+3, fill='black')

  24. # ----- 数据结构 -----
  25. board = [ [None]*9 for _ in range(10) ]

  26. def set_piece(col, row, color, ptype):
  27.     board[ row ][ col ] = {'color':color, 'type':ptype}

  28. # 初始化红方
  29. red_pieces = [
  30.     (0,9,'车'), (1,9,'马'), (2,9,'象'), (3,9,'士'), (4,9,'将'),
  31.     (5,9,'士'), (6,9,'象'), (7,9,'马'), (8,9,'车'),
  32.     (1,7,'炮'), (7,7,'炮')
  33. ]
  34. for col in range(0,9,2):
  35.     red_pieces.append((col,6,'兵'))
  36. for col,row,pt in red_pieces:
  37.     set_piece(col, row, 'red', pt)

  38. # 初始化黑方
  39. black_pieces = [
  40.     (0,0,'車'), (1,0,'馬'), (2,0,'象'), (3,0,'士'), (4,0,'将'),
  41.     (5,0,'士'), (6,0,'象'), (7,0,'馬'), (8,0,'車'),
  42.     (1,2,'炮'), (7,2,'炮')
  43. ]
  44. for col in range(0,9,2):
  45.     black_pieces.append((col,3,'卒'))
  46. for col,row,pt in black_pieces:
  47.     set_piece(col, row, 'black', pt)

  48. # ----- 画棋子函数(带tag)-----
  49. def draw_one_piece(col, row, color, text, tag='piece'):
  50.     x = padding + col * SIZE
  51.     y = padding + row * SIZE
  52.     canvas.create_oval(x-R, y-R, x+R, y+R, outline='black', width=2, tags=tag)
  53.     canvas.create_oval(x-R, y-R, x+R, y+R, fill=color, tags=tag)
  54.     canvas.create_text(x, y, text=text, font=('Arial',20,'bold'), fill='white', tags=tag)

  55. def redraw_all():
  56.     canvas.delete('piece')
  57.     for row in range(10):
  58.         for col in range(9):
  59.             piece = board[row][col]
  60.             if piece:
  61.                 color = piece['color']
  62.                 text = piece['type']
  63.                 draw_one_piece(col, row, 'red' if color=='red' else 'black', text, tag='piece')

  64. redraw_all()

  65. # ----- 鼠标交互 -------------------------------------------------
  66. selected = None   # (col, row) 当前选中的棋子

  67. def pos_to_board(px, py):
  68.     col = round((px - padding) / SIZE)
  69.     row = round((py - padding) / SIZE)
  70.     if 0 <= col <= 8 and 0 <= row <= 9:
  71.         return col, row
  72.     return None

  73. # ---------- 简单走法判断(仅供演示,只实现车、马、炮、兵的部分规则)--------
  74. def is_legal_move(piece, from_col, from_row, to_col, to_row):
  75.     # 这里仅示意,真正完整的走法规则很长。以下只判断“不走出棋盘、不吃己方”
  76.     if not (0 <= to_col <= 8 and 0 <= to_row <= 9):
  77.         return False
  78.     target = board[to_row][to_col]
  79.     if target and target['color'] == piece['color']:
  80.         return False
  81.     # 实际你应判断具体棋子类型走法,此处直接返回 True 以演示交互
  82.     return True

  83. def move_piece(from_col, from_row, to_col, to_row):
  84.     piece = board[from_row][from_col]
  85.     if not piece:
  86.         return False
  87.     if is_legal_move(piece, from_col, from_row, to_col, to_row):
  88.         board[to_row][to_col] = piece
  89.         board[from_row][from_col] = None
  90.         redraw_all()
  91.         return True
  92.     return False

  93. def ai_move():
  94.     # 随机选择一个黑方棋子,随机走一步(不考虑合法性,仅演示)
  95.     black_pieces = []
  96.     for row in range(10):
  97.         for col in range(9):
  98.             p = board[row][col]
  99.             if p and p['color'] == 'black':
  100.                 black_pieces.append((col, row))
  101.     if not black_pieces:
  102.         return
  103.     piece_pos = random.choice(black_pieces)
  104.     col, row = piece_pos
  105.     # 随机选择一个相邻位置(包括原地?不要原地)
  106.     dirs = [ (-1,0),(1,0),(0,-1),(0,1) ]
  107.     random.shuffle(dirs)
  108.     for dc, dr in dirs:
  109.         new_col = col + dc
  110.         new_row = row + dr
  111.         if 0 <= new_col <= 8 and 0 <= new_row <= 9:
  112.             target = board[new_row][new_col]
  113.             if not target or target['color'] != 'black':
  114.                 # 执行移动
  115.                 board[new_row][new_col] = board[row][col]
  116.                 board[row][col] = None
  117.                 redraw_all()
  118.                 return True
  119.     return False

  120. def on_click(event):
  121.     global selected
  122.     pos = pos_to_board(event.x, event.y)
  123.     if not pos:
  124.         return
  125.     col, row = pos
  126.     piece = board[row][col]
  127.     if selected is None:
  128.         # 第一次点击:选中己方棋子(红方)
  129.         if piece and piece['color'] == 'red':
  130.             selected = (col, row)
  131.             # 高亮选中(可选)
  132.             canvas.create_rectangle(
  133.                 padding + col*SIZE - 5, padding + row*SIZE - 5,
  134.                 padding + col*SIZE + 5, padding + row*SIZE + 5,
  135.                 outline='yellow', width=3, tags='highlight')
  136.     else:
  137.         # 第二次点击:尝试移动
  138.         from_col, from_row = selected
  139.         if move_piece(from_col, from_row, col, row):
  140.             # 移动成功,轮到AI
  141.             canvas.delete('highlight')
  142.             selected = None
  143.             ai_move()
  144.         else:
  145.             # 移动失败,取消选择
  146.             canvas.delete('highlight')
  147.             selected = None

  148. canvas.bind('<Button-1>', on_click)

  149. root.mainloop()
复制代码


---

### 说明

1. **此代码完全基于你原来的 tkinter 棋盘**,无需安装额外库。  
2. **点击红方棋子(第一次点击)** 会选中它(出现黄色小框),再点击目标位置即可移动。移动后 AI 自动走一步黑方。  
3. **AI 非常弱**:它只是随机选择一个黑方棋子,然后向随机方向移动一步(不会吃子)。你可以在此基础上实现真正的 AI(如极小极大搜索)。  
4. **走法合法性**:目前只判断了“不出棋盘、不吃己方”,没有实现具体棋子规则(车直线、马蹩脚等)。你需要根据棋子类型补充 `is_legal_move` 函数,但核心交互架构已经完整。

如果你希望用 `pygame` 版本,请在提问时明确说明。不过既然你已经写好了 tkinter 的绘制代码,建议继续用 tkinter 完成,因为两者切换会带来额外工作量。

现在请将你原有的 `pygame` 相关代码全部删除,只保留上面这段完整的 tkinter 代码并运行。祝你成功!

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
棋子吃完了没赢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:46
棋子吃完了没赢


你的代码中缺少“胜利判定”,所以即使吃掉所有棋子,游戏也不会停止。根据你描述的“棋子吃完了没赢”,有两种常见情况:  

- **简化规则**:一方所有棋子被吃光即获胜(不含将/帅)。  
- **标准规则**:将/帅被将死才获胜。  

我建议你先用“简化规则”测试,因为实现最简单。请在鼠标点击移动成功后,添加如下检查:  

  1.   
  2. # 在 on_click 函数移动成功后,添加胜利判断  
  3. def check_winner():  
  4.     red_exists = False  
  5.     black_exists = False  
  6.     for row in range(10):  
  7.         for col in range(9):  
  8.             piece = board[row][col]  
  9.             if piece:  
  10.                 if piece['color'] == 'red':  
  11.                     red_exists = True  
  12.                 else:  
  13.                     black_exists = True  
  14.     if not red_exists:  
  15.         print("黑方获胜!")  
  16.         canvas.create_text(350, 375, text="黑方胜利!", font=('Arial', 30, 'bold'), fill='black', tags='message')  
  17.         return 'black'  
  18.     elif not black_exists:  
  19.         print("红方获胜!")  
  20.         canvas.create_text(350, 375, text="红方胜利!", font=('Arial', 30, 'bold'), fill='red', tags='message')  
  21.         return 'red'  
  22.     return None  
复制代码


然后在 `move_piece` 成功移动后(即在 `board[target_row][target_col] = piece` 和 `board[start_row][start_col] = None` 之后),调用 `check_winner()`。如果返回非空,则禁用鼠标点击(例如设置一个全局标志 `game_over = True`,在 `on_click` 开头判断并直接返回)。  

完整的 `move_piece` 修改示例(加入胜利检查):  

  1.   
  2. def move_piece(start_col, start_row, target_col, target_row):  
  3.     global selected, game_over  
  4.     if game_over:  
  5.         return False  
  6.     # ...(之前的移动合法性检查代码)  
  7.     # 假设已经判断合法,执行移动  
  8.     piece = board[start_row][start_col]  
  9.     board[target_row][target_col] = piece  
  10.     board[start_row][start_col] = None  
  11.     redraw_all()  
  12.     winner = check_winner()  
  13.     if winner:  
  14.         game_over = True  
  15.         # 可选:2秒后关闭窗口  
  16.         root.after(2000, root.quit)  
  17.     return True  
复制代码


别忘了在最开始定义 `game_over = False`。这样当一方棋子被吃光后,棋盘中央会显示胜利文字,游戏结束。  

如果你希望实现“将死”判定(标准规则),则需要额外编写将军检测和逃生判断,这比较复杂。建议先从“吃光胜利”开始,确认移动逻辑无误后,再逐步完善。

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-7-15 08:46
你的代码中缺少“胜利判定”,所以即使吃掉所有棋子,游戏也不会停止。根据你描述的“棋子吃完了没赢” ...

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
  File "C:/Program Files/Python38/hueizhi.py", line 196, in on_click
    if move_piece(from_col, from_row, col, row):
  File "C:/Program Files/Python38/hueizhi.py", line 161, in move_piece
    if game_over:
NameError: name 'game_over' is not defined
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
过默 发表于 2026-07-15 08:49
FishC 发表于 2026-7-15 08:46
你的代码中缺少“胜利 ...


你遇到的错误是因为在 `move_piece` 函数里使用了 `game_over` 变量,但你没有在程序开头定义它。请在代码最前(`import` 之后,所有函数定义之前)加上这一行:

game_over = False

另外,你的 `on_click` 函数中引用了 `selected`、`from_col`、`from_row` 等变量,需要确保它们也已被定义。如果你之前的代码中已经定义了 `selected = None`,那就没问题。但如果未定义,还需加上:

selected = None

完整的修正步骤如下:

1. 找到你代码的开头部分,在 `import tkinter` 和 `import random` 之后,添加:
   game_over = False
   selected = None

2. 确保 `move_piece` 函数内部正确使用了这些全局变量。例如,在 `move_piece` 函数的第一行添加 `global game_over`(如果要对 `game_over` 赋值)。但如果你只是在开头判断 `if game_over:` 而不修改它,可以不加 global。但为了安全,建议在函数内部访问全局变量时声明 `global game_over, selected`(如果需要修改 selected)。

3. 检查你的 `move_piece` 函数是否正确地调用了 `board`、`redraw_all` 等。如果依然报错,很可能是因为 `board` 变量作用域问题(函数内未声明 global)。请确认你的 `board` 是在全局定义的列表,并且在 `move_piece` 中要修改它,必须写 `global board`。

下面是一个安全的结构示例(仅展示修正部分,请根据你的实际代码位置插入):

import tkinter as tk
import random

# ... 定义常量 SIZE, R, padding ...
# ... 画棋盘的代码 ...
board = [ *9 for _ in range(10) ]   # 全局棋盘数据
game_over = False                   # 添加这一行
selected = None                     # 添加这一行

def draw_one_piece(col, row, color, text, tag='piece'):
    # ... 你的绘图代码 ...

def redraw_all():
    # ... 重绘所有棋子 ...

def move_piece(from_col, from_row, target_col, target_row):
    global board, game_over   # 告诉 Python 要修改这两个全局变量
    if game_over:
        return False
    # ... 移动合法性判断 ...
    # 假设合法,执行移动
    board = board   # 复制引用
    board = None
    redraw_all()
    # 检查胜负
    winner = check_winner()  # 假设你有这个函数
    if winner:
        game_over = True
        canvas.create_text(350, 375, text=winner+'方胜利!', ...)
    return True

def on_click(event):
    global selected, game_over
    if game_over:
        return
    # ... 你的点击处理逻辑,确保用了 selected, from_col, from_row ...

# 然后绑定 canvas.bind('<Button-1>', on_click)
root.mainloop()

请对照你的代码,加入 `game_over` 和 `selected` 的全局定义,并在需要修改它们的函数内添加 `global` 声明。这样就不会再出现 `NameError` 了。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-15 13:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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