|
|
好的,鱼油!你想用 `pygame` 实现可视化象棋并检测飞刀,没问题。下面给你一个精简但完整的 `pygame` 象棋程序框架,包括:棋盘绘制、鼠标点击走棋(UCI格式)、飞刀检测。你复制就能运行,需要先 `pip install pygame`。
**代码**(文件保存为 chess_with_trap.py,直接运行)
- import pygame
- import sys
- # ---------- 飞刀库 ----------
- KNOWN_TRAPS = [
- ("测试飞刀", ["e2e4", "e7e5", "d2d4"]),
- ]
- def match_trap(history):
- for name, seq in KNOWN_TRAPS:
- if len(history) >= len(seq) and history[-len(seq):] == seq:
- return name
- return None
- # ---------- 棋盘和棋子 ----------
- BOARD_SIZE = 8
- SQUARE_SIZE = 80
- WIDTH = HEIGHT = SQUARE_SIZE * BOARD_SIZE
- # 初始局面(FEN字符串简化)
- INITIAL_PIECES = {
- # 黑方
- "a8":"br","b8":"bn","c8":"bb","d8":"bq","e8":"bk","f8":"bb","g8":"bn","h8":"br",
- "a7":"bp","b7":"bp","c7":"bp","d7":"bp","e7":"bp","f7":"bp","g7":"bp","h7":"bp",
- # 白方
- "a2":"wp","b2":"wp","c2":"wp","d2":"wp","e2":"wp","f2":"wp","g2":"wp","h2":"wp",
- "a1":"wr","b1":"wn","c1":"wb","d1":"wq","e1":"wk","f1":"wb","g1":"wn","h1":"wr",
- }
- def pos_to_uci(col, row):
- # 将像素坐标转为UCI字符串(如 'e2')
- file = chr(ord('a') + col)
- rank = str(8 - row)
- return file + rank
- class ChessGame:
- def __init__(self):
- pygame.init()
- self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
- pygame.display.set_caption("象棋飞刀检测")
- self.clock = pygame.time.Clock()
- self.font = pygame.font.SysFont(None, 48)
- self.reset_board()
- def reset_board(self):
- self.board = {} # uci -> piece string, e.g. "e2" -> "wp"
- for pos, piece in INITIAL_PIECES.items():
- self.board[pos] = piece
- self.selected = None
- self.history = []
- self.trap_message = ""
- def draw_board(self):
- colors = [(240, 217, 181), (181, 136, 99)]
- for row in range(8):
- for col in range(8):
- color = colors[(row + col) % 2]
- pygame.draw.rect(self.screen, color, (col*SQUARE_SIZE, row*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))
- # 绘制棋子
- for pos, piece in self.board.items():
- col = ord(pos[0]) - ord('a')
- row = 8 - int(pos[1])
- x = col * SQUARE_SIZE + SQUARE_SIZE//2
- y = row * SQUARE_SIZE + SQUARE_SIZE//2
- color = (0,0,0) if piece[0]=='b' else (255,255,255)
- pygame.draw.circle(self.screen, color, (x, y), SQUARE_SIZE//2 - 4)
- # 棋子符号
- label = piece[1].upper()
- text = self.font.render(label, True, (255,255,255) if piece[0]=='b' else (0,0,0))
- text_rect = text.get_rect(center=(x,y))
- self.screen.blit(text, text_rect)
- # 显示飞刀检测结果
- if self.trap_message:
- msg = self.font.render(self.trap_message, True, (255,0,0))
- self.screen.blit(msg, (10, HEIGHT-40))
- def handle_click(self, pos):
- col = pos[0] // SQUARE_SIZE
- row = pos[1] // SQUARE_SIZE
- uci = pos_to_uci(col, row)
- if self.selected is None:
- # 选择起点
- if uci in self.board:
- self.selected = uci
- else:
- # 尝试走棋
- src = self.selected
- dst = uci
- move = src + dst
- if move[0:2] in self.board:
- # 简单的走棋(不验证合法性)
- self.board[dst] = self.board.pop(src)
- self.history.append(move)
- # 检测飞刀
- trap = match_trap(self.history)
- self.trap_message = f" 中了飞刀:{trap}" if trap else ""
- self.selected = None
- else:
- self.selected = None
- def run(self):
- running = True
- while running:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- running = False
- elif event.type == pygame.MOUSEBUTTONDOWN:
- self.handle_click(event.pos)
- self.draw_board()
- pygame.display.flip()
- self.clock.tick(30)
- pygame.quit()
- sys.exit()
- if __name__ == "__main__":
- game = ChessGame()
- game.run()
复制代码
**说明**
- 代码使用了最基本的 pygame 绘图,点击棋子(选起点)再点击目标格(走棋),自动将走法加入 `history`。
- 每次走完后检测 `history` 是否匹配 `KNOWN_TRAPS` 中的序列(最后几步匹配)。
- 屏幕底部会显示是否中了飞刀(红色文字)。
- **飞刀库**:你可以在 `KNOWN_TRAPS` 中添加真实陷阱,例如:
- KNOWN_TRAPS = [
- ("弃马十三招", ["e2e4", "e7e5", "g1f3", "b8c6", "f1c4", "f7f5"]), # 示例,需填写真实走法
- ]
复制代码
**运行效果**
- 窗口显示棋盘,棋子为圆形+字符表示(w=白,b=黑)。
- 点击棋子选中,再点击目标格走棋。
- 连续走三步(如 e2e4 → e7e5 → d2d4)后,底部会显示“中了飞刀:测试飞刀”。
**注意事项**
- 此代码**不验证走棋合法性**,只做移动演示。如需完整规则,需要增加合法性判断。
- 建议将真实的飞刀棋谱按UCI顺序写在 `KNOWN_TRAPS` 中。
- 如果棋子图像想用图片,可以替换绘制部分,但字符版已经够用。
现在直接复制运行,你就有一个带飞刀检测的 pygame 象棋了!快去试试吧。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|