AI Slop 警告!
零第三方依赖的终端贪吃蛇游戏。采用分层模块化架构(core / log / render / input),
全部模块经 main 组装;架构细节见 DESIGN.md。
听了 jyy 老师的《生成式软件工程》网课,随便想搞一个 CLI 贪吃蛇游戏,结果初次生成结果不理想。经由 AI 分析后认为是单次提示密度过高,又缺乏可执行的验收标准,又刚好和网课内容对上了。于是参考 OpenSpec 的核心思想,先让 Kimi K3 输出设计文档(不出意外的五小时额度很快用光了),后由 Deepseek V4Flash 分模块实现,最后验收通过。
在细节上还有一些问题亟待处理,但是此次尝试目的已经达成了,细枝末节上的东西有时间再来处理吧。
.
├── DESIGN.md # 架构设计文档
├── CMakeLists.txt # CMake 构建
├── main.cpp # 组装层:主循环,poll → turn → tick → draw/log
│
├── core/ # 纯游戏逻辑
│ ├── types.hpp # Position / Direction 值类型
│ ├── snake.hpp # 蛇实体:移动、生长、转向
│ ├── fruit.hpp # 果实:随机重放置
│ └── game_state.hpp # 状态机:tick 编排、胜负判定、产出 TickResult
├── log/ # 日志模块
│ ├── log_entry.hpp # LogEntry 序列化 / 严格解析
│ └── logger.hpp # GameLogger:订阅 tick 累积,局末追加写 snake.log
├── render/ # 渲染模块
│ └── renderer.hpp # IRenderer:只读消费 GameState;边框 + 反转日志行
├── input/ # 输入模块
│ └── input_handler.hpp # 非阻塞按键 → 方向命令;长按节流
│
├── snake.cpp fruit.cpp game_state.cpp # core 实现
├── log_entry.cpp logger.cpp # log 实现
├── renderer.cpp # render 实现
├── input_handler.cpp # input 实现
└── tests/
├── game_tests.cpp # 纯游戏逻辑单元测试
└── log_tests.cpp # 日志序列化 / GameLogger 单元测试
设计要点:render / input / log 三者互不包含头文件,只通过 core
的 TickResult / Direction 数据结构间接通信,每个模块可独立替换。
| 项目 | 要求 |
|---|---|
| 操作系统 | Linux(依赖 termios、poll(2)、unistd 等 POSIX 接口;macOS 理论可用但未测试,Windows 需 WSL / 类 Unix 环境) |
| 终端 | 支持 ANSI 转义序列(清屏/光标定位)与 UTF-8(箭头、× 为多字节字符) |
| 编译器 | 支持 C++23(代码使用 std::expected、三路比较等;建议 GCC ≥ 13 或 Clang ≥ 16) |
| CMake | ≥ 3.16(仅单元测试需要;直接 g++ 编译不需要) |
| 第三方依赖 | 无(零依赖,不依赖 ncurses) |
| 项目 | 版本 |
|---|---|
| 操作系统 | Arch Linux,内核 7.2.3-arch1-2(x86_64) |
| 编译器 | GCC 16.2.1(g++),Clang 22.1.8 |
| CMake | 4.4.3 |
已验证:g++ -std=c++23 *.cpp -o snake 编译通过(-Wall -Wextra 无警告),
ctest 两个测试套件 100% 通过。
# 方式一:快速编译(零依赖、无需 CMake)
g++ -std=c++23 *.cpp -o snake
# 方式二:CMake 构建 + 单元测试
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failure
# 运行游戏(默认 20×20)
./snake
./snake 20 20 # 指定棋盘:宽 高
./snake 5 8
# 回放模式:把指定日志行渲染为 CLI 画面(最下行显示反转后的日志行)
./snake --replay '{2×2}[2×2](1×1)→↓←↑{W}'| 操作 | 行为 |
|---|---|
方向键 ↑↓←→ 或 W A S D |
控制蛇头方向 |
| 短按 | 按一次,蛇移动一步 |
| 长按 | 按住方向键,每秒最多识别 4 次 |
| 无输入 | 蛇静止,日志不变 |
q / Q / Ctrl-C |
退出游戏 |
| 对局结束 | 自动把本局日志行追加写入 snake.log({W} 胜 / {L} 负) |
画面布局:上方为带边框的棋盘(@@ 蛇头、## 蛇身、** 果实),
最下方一行显示反转后的日志字符串(括号段保持完整,顺序倒序)。
单行、无空白、UTF-8,格式为:
{n×m}[i×j](i×j)→↓←↑(i×j){W|L}
{n×m}棋盘:n 列 × m 行[i×j]初始蛇头(1 基,行×列)(i×j)果实序列(含首个,每次放置按序追加)→↓←↑方向流(每 tick 恰好一个字符){W}/{L}结局(解析时可省略,缺省为{L})
示例:{20×20}[9×10](10×11)→→↓←(20×20)。
完整规范与往返不变量见 DESIGN.md §3。