Files
NewWPSBot/.past_tasks/2025-10-28_1_gomoku.md

272 lines
9.7 KiB
Markdown
Raw Normal View History

2025-11-06 16:26:07 +08:00
# 背景
文件名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)`作为唯一键
- 五子棋需要双人对战,需要同时记录两个玩家
- 需要设计状态数据结构,存储:
- 对战双方IDplayer1_id, player2_id
- 当前轮到谁current_player_id
- 棋盘状态15x15二维数组
- 游戏状态waiting, playing, finished
- 胜者IDwinner_id如果有
### 2. 多轮对战并发
- 允许同一个chat中有多轮对战只要对战双方不同
- 需要一个机制来标识不同的对战局可以用对战双方ID的组合
- 状态查询需要能够找到特定用户参与的对战
### 3. 禁手规则实现
禁手规则(仅对黑方,即先手玩家):
- **三三禁手**:一手棋同时形成两个或以上的活三
- **四四禁手**:一手棋同时形成两个或以上的活四或冲四
- **长连禁手**:一手棋形成六子或以上的连珠
需要实现:
- 判断某个位置的四个方向(横、竖、左斜、右斜)的连珠情况
- 判断活三、活四、冲四的定义
- 在落子时检查是否触发禁手
### 4. 坐标系统
-A-O15列
-1-1515行
- 需要坐标转换函数:`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 @用户格式 `<at user_id="xxx"></at>` 进行解析
- 修改所有用户显示,从 `@用户{user_id}` 改为 `<at user_id="{user_id}"></at>`,以正确显示用户的群名称
- 涉及修改:开始游戏、落子、显示棋盘、认输、列出对战等所有用户显示位置
- 原因:修复用户识别失败和显示错误的问题
- 阻碍因素:用户识别仍然失败
- 状态:不成功
## [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代码块中正确对齐
- 原因:修复用户反馈的棋盘文本对齐问题
- 阻碍因素:无
- 状态:未确认
# 最终审查
(待完成后填写)