一副下在终端里的围棋。Rust + Ratatui + Crossterm。设计灵感取自围棋器具的真实材质:板岩黑子、蛤贝白子、榧木棋盘。
注意:最近一手棋子旁的
▪是朱砂红落款印("印"字的视觉替身),是整个设计的签名元素 — 模拟中国书画落款旁的印章。
双人热座,同一台终端轮流落子。
cargo run # 默认 19×19
cargo run -- --size 9 # 9 路小棋盘
cargo run -- --size 13 # 13 路中棋盘
cargo run -- --size 19 # 19 路标准最小终端尺寸要求:
- 9×9 棋盘:约 60×16
- 13×13 棋盘:约 68×20
- 19×19 棋盘:约 80×26
终端过小时,应用会立即提示并退出,不会显示坏掉的界面。
| 键 | 动作 |
|---|---|
← ↑ ↓ → 或 hjkl |
移动光标 |
Enter 或 Space |
落子(结算模式下 = 确认结算) |
u |
悔棋 |
r |
认输(再按 y 确认) |
e |
进入主动结算模式(演化中 = 加速完成) |
? |
切换按键帮助浮层 |
q 或 Esc |
退出(结算模式下 = 取消结算) |
按 e 进入结算模式后:
| 键 | 动作 |
|---|---|
d |
切换光标群组的死/活(整群一起标) |
Enter / e |
确认结算,进入演化终局 |
e |
演化中加速完成 |
Esc / q |
取消结算 / 取消演化,退回对局 |
死子在棋盘上以 ✕(灰底加粗)渲染。
确认结算后并不直接算分:死子先行清场,腾出的位置成为新生的土壤,棋盘随即按一套 4-连接的生命游戏规则自动演化 5 代(每代 300ms),黑白各自独立演化:
- 活子存活:同色邻子恰为 2 或 3 枚
- 空点诞生:恰好 3 枚邻子且全部同色,生出一枚该色之子
- 其余情形,活子死亡、空点保持
演化结束后,基于演化终盘计算领地与胜负。结算公式(中国规则区域计分,让子 7.5):
- 黑分 = 黑活子数 + 黑领地数
- 白分 = 白活子数 + 白领地数 + 7.5
领地为:BFS 找空地区域,只邻接一种颜色 → 该色领地;邻接双方 → 中立(不计分)。
完整围棋规则三件套:
- 吃子:被围住气为 0 的对方群组被提走,提子数计入己方提子栏。
- 禁自杀:落子后自己所在群组气为 0 且未提任何对方子 → 拒绝落子,状态栏提示 "禁止自杀"。
- 打劫 (positional superko):禁止重复任何已出现过的局面。状态栏提示 "禁止打劫"。
侧栏实时显示双方已提子数、印池(上一手 + 朱砂印)与最近 20 手落子记录。终局以认输或主动结算结束,两种方式都会锁定棋盘;主动结算经演化终局后按中国规则区域计分法判定胜负。
src/
├── main.rs # CLI 参数 + 启动流程
├── app.rs # 主循环 + 终端尺寸校验 + 演化节奏
├── input.rs # 键盘映射 + 错误码翻译
├── game/
│ ├── mod.rs # GameState + 顶层 play/undo API + 演化终局
│ ├── board.rs # Vec<Option<Color>> + 星位
│ ├── coords.rs # "D4" ↔ (col, row), 全角转换
│ ├── rules.rs # BFS 群组 + 提子 + 禁自杀 + Zobrist 哈希 + tick_life
│ └── history.rs # MoveRecord + 悔棋栈 + 打劫位置集合
└── ui/
├── mod.rs # render() 总入口
├── layout.rs # 棋盘 / 棋谱 / 状态栏 切分
├── board.rs # 棋盘 + 棋子 + 光标 + 落款印
├── seal.rs # 印池:上手坐标 + 朱砂印大字
├── sidebar.rs # 提子 + 领地 + 落子记录
├── statusbar.rs # 当前玩家 + 光标 + 按键提示
├── help.rs # 全屏按键帮助浮层
└── theme.rs # 调色板 + Unicode 字符常量
调色板(来自真实器物质感)
| Token | Hex | 含义 |
|---|---|---|
BG_PANEL |
#1B1612 |
暗墨色面板底 |
BG_BOARD |
#2E2519 |
榧木棋盘 |
GRID_HARD |
#4A3D2A |
主网格线 |
GRID_SOFT |
#3A2F1F |
星位 / 天元 |
STONE_BLACK_BG |
#0A0A0A |
板岩黑子底 |
STONE_WHITE_BG |
#EFE4C9 |
蛤贝白子底 |
CURSOR_HALO |
#D4A56A |
琥珀金光标晕 |
SEAL_RED |
#B2343A |
朱砂红落款印 |
TEXT_DIM |
#8E7B5E |
暖灰弱化文字 |
TEXT_MAIN |
#D9C9A6 |
米黄主文字 |
BORDER_GOLD |
#6B5535 |
青铜边框 |
签名元素
落款印(▪,朱砂红)— 模拟中国书画落款旁的印章 chop mark。视觉上把"上一手"从"标记"提升为"签名";侧栏的印池组件则将其放大为一方独立印章。
cargo test # 94 个单元测试(game 规则 + ui 渲染)
cargo build --release # 发布构建测试覆盖:
- 落子 / 提子基本流程
- 禁自杀(边角 / 中腹)
- 多群组同时被提(双叫吃 / 大飞枷)
- 简单打劫(positional superko)
- 坐标转换(半角 / 全角 / 跳过 I)
- 悔棋还原(含被提子按原色放回)
- 生命游戏演化(存活 / 死亡 / 诞生 / 静止)
- ui 渲染(印池 / 提子堆 / 领地 / 帮助浮层)
- 不支持虚手(Pass):对局以认输或主动结算结束。
- 不支持 SGF 导入导出。
- 不支持 AI / 单人对战。
- 死活无自动判定,结算时需手动标记死子。
- 终端需为现代真彩(truecolor)UTF-8 终端(iTerm2 / Alacritty / kitty / Windows Terminal / GNOME Terminal)。Linux TTY 控制台会渲染颜色但不支持全角字符宽度。
