# 背景 文件名:2025-10-28_1_gomoku.md 创建于:2025-10-28_17:08:29 创建者:User 主分支:main 任务分支:task/gomoku_2025-10-28_1 Yolo模式:Off # 任务描述 创建一个五子棋(Gomoku)游戏模块,支持双人对战功能。 ## 核心需求 1. **游戏模式**:双人对战(两个用户在同一个聊天中对战) 2. **棋盘规格**:标准15x15棋盘 3. **禁手规则**:需要实现禁手规则(三三禁手、四四禁手、长连禁手) 4. **超时规则**:不需要回合时间限制 5. **并发对战**:允许多轮对战同时存在,只要交战双方不同即可 6. **显示方式**:使用emoji绘制棋盘(⚫⚪➕)+ 坐标系统(A-O列,1-15行) ## 功能清单 - 开始游戏:`.gomoku start @对手` 或 `.gomoku @对手` - 落子:`.gomoku A1` 或 `.gomoku 落子 A1` - 认输:`.gomoku resign` 或 `.gomoku 认输` - 查看棋盘:`.gomoku show` 或 `.gomoku 查看` - 查看战绩:`.gomoku stats` 或 `.gomoku 战绩` - 帮助信息:`.gomoku help` 或 `.gomoku 帮助` ## 技术要点 1. 继承`BaseGame`基类 2. 游戏状态存储在数据库中(使用chat_id + 对战双方ID作为键) 3. 需要实现五子棋禁手规则的判定逻辑 4. 需要实现胜负判定(五子连珠) 5. 棋盘使用二维数组表示,支持坐标转换(A-O, 1-15) # 项目概览 ## 现有架构 - **框架**:FastAPI - **数据库**:SQLite(使用标准库sqlite3) - **游戏基类**:`games/base.py - BaseGame` - **路由处理**:`routers/callback.py` - **数据库操作**:`core/database.py - Database类` ## 现有游戏 - 石头剪刀布(rps) - 问答游戏(quiz) - 猜数字(guess) - 成语接龙(idiom) - 骰娘系统(dice) - 运势占卜(fortune) ## 数据库表结构 1. **users**:用户基本信息 2. **game_states**:游戏状态(支持chat_id, user_id, game_type的唯一约束) 3. **game_stats**:游戏统计(wins, losses, draws, total_plays) # 分析 ## 核心挑战 ### 1. 游戏状态管理 - 现有的`game_states`表使用`(chat_id, user_id, game_type)`作为唯一键 - 五子棋需要双人对战,需要同时记录两个玩家 - 需要设计状态数据结构,存储: - 对战双方ID(player1_id, player2_id) - 当前轮到谁(current_player_id) - 棋盘状态(15x15二维数组) - 游戏状态(waiting, playing, finished) - 胜者ID(winner_id,如果有) ### 2. 多轮对战并发 - 允许同一个chat中有多轮对战,只要对战双方不同 - 需要一个机制来标识不同的对战局(可以用对战双方ID的组合) - 状态查询需要能够找到特定用户参与的对战 ### 3. 禁手规则实现 禁手规则(仅对黑方,即先手玩家): - **三三禁手**:一手棋同时形成两个或以上的活三 - **四四禁手**:一手棋同时形成两个或以上的活四或冲四 - **长连禁手**:一手棋形成六子或以上的连珠 需要实现: - 判断某个位置的四个方向(横、竖、左斜、右斜)的连珠情况 - 判断活三、活四、冲四的定义 - 在落子时检查是否触发禁手 ### 4. 坐标系统 - 列:A-O(15列) - 行:1-15(15行) - 需要坐标转换函数:`parse_coord("A1") -> (0, 0)` - 需要显示转换函数:`format_coord(0, 0) -> "A1"` ### 5. 棋盘显示 使用emoji: - ⚫ 黑子(先手) - ⚪ 白子(后手) - ➕ 空位 - 需要添加行号和列号标注 示例: ``` A B C D E F G H I J K L M N O 1 ➕➕➕➕➕➕➕➕➕➕➕➕➕➕➕ 2 ➕➕➕➕➕➕➕➕➕➕➕➕➕➕➕ 3 ➕➕⚫➕➕➕➕➕➕➕➕➕➕➕➕ ... ``` ## 数据结构设计 ### state_data结构 ```python { "player1_id": 123456, # 黑方(先手) "player2_id": 789012, # 白方(后手) "current_player": 123456, # 当前轮到谁 "board": [[0]*15 for _ in range(15)], # 0:空, 1:黑, 2:白 "status": "playing", # waiting, playing, finished "winner_id": None, # 胜者ID "moves": [], # 历史落子记录 [(row, col, player_id), ...] "last_move": None # 最后一手 (row, col) } ``` ### 游戏状态存储策略 - 使用chat_id作为会话ID - 使用较小的user_id作为主键中的user_id(保证唯一性) - 在state_data中存储完整的对战信息 - 查询时需要检查用户是否是player1或player2 # 提议的解决方案 ## 方案选择 使用现有的数据库表结构,通过精心设计state_data来支持双人对战。 ## 实现方案 ### 1. 游戏类:`games/gomoku.py` 继承`BaseGame`,实现以下方法: - `handle()` - 主处理逻辑 - `get_help()` - 帮助信息 - `_start_game()` - 开始游戏 - `_make_move()` - 落子 - `_show_board()` - 显示棋盘 - `_resign()` - 认输 - `_get_stats()` - 查看战绩 ### 2. 五子棋逻辑:单独模块或工具类 - `_parse_coord()` - 解析坐标 - `_format_coord()` - 格式化坐标 - `_render_board()` - 渲染棋盘 - `_check_win()` - 检查胜负 - `_check_forbidden()` - 检查禁手 - `_is_valid_move()` - 检查落子是否合法 ### 3. 禁手检测逻辑 实现辅助方法: - `_count_line()` - 统计某方向的连珠情况 - `_is_live_three()` - 判断活三 - `_is_live_four()` - 判断活四 - `_is_rush_four()` - 判断冲四 - `_check_three_three()` - 检查三三禁手 - `_check_four_four()` - 检查四四禁手 - `_check_overline()` - 检查长连禁手 ### 4. 状态管理 - 使用`min(player1_id, player2_id)`作为数据库中的user_id - 在state_data中完整存储对战信息 - 提供辅助方法查找用户当前参与的游戏 ### 5. 路由注册 在`routers/callback.py`的`handle_command()`函数中添加: ```python if game_type == 'gomoku': from games.gomoku import GomokuGame game = GomokuGame() return await game.handle(command, chat_id, user_id) ``` ### 6. 指令解析 在`utils/parser.py`的`CommandParser`类中添加gomoku指令识别 ### 7. 配置更新 在`config.py`中添加五子棋相关配置(如果需要) # 当前执行步骤:"已完成所有实施步骤" # 任务进度 ## [2025-10-28 17:18:21] - 已修改: - config.py - 添加gomoku配置 - utils/parser.py - 添加gomoku指令映射 - games/gomoku_logic.py - 创建五子棋逻辑模块(新文件) - games/gomoku.py - 创建五子棋游戏类(新文件) - routers/callback.py - 添加gomoku路由 - games/base.py - 更新帮助信息和统计信息 - 更改:完成五子棋游戏的完整实现,包括: - 群级游戏池管理(支持多轮对战并存) - 标准15x15棋盘 - 完整的禁手规则(三三、四四、长连) - 坐标系统(A-O列,1-15行) - emoji棋盘渲染(⚫⚪➕) - 胜负判定 - 战绩统计 - 原因:实现用户需求的双人对战五子棋游戏 - 阻碍因素:用户识别和显示格式错误 - 状态:不成功 ## [2025-10-28 17:36:07] - 已修改: - games/gomoku.py - 修复用户识别和显示格式 - 更改: - 修复 `_parse_opponent()` 方法,使用正确的WPS @用户格式 `` 进行解析 - 修改所有用户显示,从 `@用户{user_id}` 改为 ``,以正确显示用户的群名称 - 涉及修改:开始游戏、落子、显示棋盘、认输、列出对战等所有用户显示位置 - 原因:修复用户识别失败和显示错误的问题 - 阻碍因素:用户识别仍然失败 - 状态:不成功 ## [2025-10-28 17:42:24] - 已修改: - games/gomoku.py - 改进用户ID解析和添加调试日志 - routers/callback.py - 增强日志输出 - 更改: - 改进 `_parse_opponent()` 方法,支持多种@用户格式(双引号、单引号、不同的标签格式) - 在 `handle()` 方法中添加详细的调试日志(command, args, action, opponent_id) - 改进错误提示,显示实际接收到的参数内容 - 将 callback.py 中的消息内容日志级别从 DEBUG 改为 INFO,便于追踪 - 原因:进一步诊断用户ID识别失败的问题,添加调试信息帮助定位问题 - 阻碍因素:WPS callback不提供被@用户的ID信息 - 状态:不成功 ## [2025-10-28 17:55:00] - 已修改: - games/gomoku.py - 重构游戏发起机制,从@用户改为挑战-接受模式 - games/base.py - 更新全局帮助信息 - routers/callback.py - 添加完整callback数据日志 - 更改: - **核心架构变更**:从"@用户发起对战"改为"挑战-接受"机制 - 新增 `_create_challenge()` 方法 - 用户发起挑战 - 新增 `_accept_challenge()` 方法 - 其他用户接受挑战 - 新增 `_cancel_challenge()` 方法 - 取消自己的挑战 - 删除 `_parse_opponent()` 方法(不再需要) - 删除 `_start_game()` 方法(由新方法替代) - 更新游戏池数据结构,添加 `challenges` 列表 - 更新所有帮助信息和错误提示 - 指令变更: - `.gomoku challenge` / `.gomoku start` - 发起挑战 - `.gomoku accept` / `.gomoku join` - 接受挑战 - `.gomoku cancel` - 取消挑战 - 原因:WPS callback消息内容中@用户只是文本形式(如"@揭英飙"),不包含user_id,无法实现@用户发起对战 - 阻碍因素:无 - 状态:成功 ## [2025-10-28 17:56:03] - 已修改: - games/gomoku_logic.py - 修复棋盘对齐问题 - 更改: - 优化 `render_board()` 函数的格式化逻辑 - 列标题:每个字母后面加一个空格,确保与棋子列对齐 - 行号:调整前导空格,从 " {row_num} " 改为 "{row_num} " - 棋子:每个emoji后面加一个空格,行尾去除多余空格 - 整体对齐:确保列标题、行号、棋子三者在Markdown代码块中正确对齐 - 原因:修复用户反馈的棋盘文本对齐问题 - 阻碍因素:无 - 状态:未确认 # 最终审查 (待完成后填写)