# snaker **Repository Path**: crisq/snaker ## Basic Information - **Project Name**: snaker - **Description**: 小学期贪吃蛇项目 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-07-14 - **Last Updated**: 2026-07-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 游戏设计 1. 双方各控制一个蒜头,每个蒜头由: - **中枢(Head)**:当前控制的位置,玩家每回合选择移动方向。 - **躯干(Body)**:随着长度增长逐渐生成,占据不可重复的位置。 > 双方每回合同步行动,无法提前知道对方本回合的移动结果。 2. 地图为 `n × m` 的二维网格。 每个格子类型: | 类型 | 符号 | 说明 | |---|---|---| | 石墙 | `#` | 不可进入,不可被破坏 | | 普通地面 | `.` | 可移动,可放置道具 | | 苹果 | `o` | 吃掉后长度 +1 | | 护盾 | `O` | 吃掉后长度 +1,并获得护盾状态 | | 蒜头1区域 | `1` | 初始位置标记 | | 蒜头2区域 | `2` | 初始位置标记 | | 重叠区域 | `3` | 双方初始区域重叠 | > 坐标采用 0-based: > `(x, y)` 表示第 `x` 行、第 `y` 列。 3. 道具: - 游戏开始时地图中随机生成一定数量的道具。 - 游戏过程中始终保持固定数量的道具。 - 当道具被吃掉后,会在随机地面位置生成新的道具。 - 苹果道具:长度+1;护盾道具:长度+1并获得20回合的护盾效果(与无护盾玩家碰撞时无护盾玩家死亡) - 双方都有护盾或都无时,长一方杀死短一方 4. 缩圈 地图会随着游戏进行逐渐缩小。 缩圈周期:`ceil(n*m*4 / min(n,m))`。 缩圈发生在回合开始时,只把新边界刷成墙;如果蛇头被刷进墙内, 不会立刻死亡。随后玩家提交的目标格若是墙、越界或身体碰撞,才按 对应原因死亡;若能走到内侧合法空格,则可以逃出。 5. 初始长度:`ceil(3*(n+m)/8)`(初始蛇身仅头部 1 格,靠 `score > len(body)` 不 pop 尾自动增长,不向地图中心延伸) 6. 单局最多 `10*n*m` 回合;`--max-rounds` 只能设置更小的提前结束上限。 ## 评测系统 算法统一使用 C++11 编译,可使用 C 风格或 C++,并保持 `src/include/playerbase.h` 中的接口不变: ```c void init(struct Player *player); struct Point walk(struct Player *player); ``` 单局运行: ```bash cd src python3 -m pip install -r requirements.txt ./run.sh algos/a.c algos/b.c --map data/day3/map2.txt --seed 1 ``` 添加 `-v` 可打开实时 Pygame 对局;空格暂停/继续,右方向键单步,Esc 退出: ```bash ./run.sh algos/a.c algos/b.c -v ``` 并行 benchmark: ```bash ./bench.py \ --algos 'algos/team_a/*.c' \ --opponents 'algos/team_b/*.c' \ --maps 'data/day*/*.txt' \ --repeats 3 --jobs 4 --out bench.csv ``` 评测热路径全部位于 `judge/match_runner.cpp`。每场比赛启动两个独立的 `player_host + algo` 进程,通过专用二进制文件描述符通信;算法的 stdin/stdout 不承载协议。Python 仅负责编译、启动独立比赛和汇总一次性的 JSON 结果,因此 `run` 与 `bench` 使用同一个规则实现。 可视化模式只消费 native runner 的只读帧,不参与玩家通信或规则判定。 算法文件(包括 `.c`)使用 `g++ -std=c++11` 编译,因此可直接使用 STL。 每位选手每步限时 100ms。 benchmark 运行时会动态刷新胜率与排名,默认并发数为逻辑 CPU 数的一半,可用 `--jobs` 调整;Rich 负责终端实时渲染,并在结束时按算法汇总死亡原因。 完整结果写入 CSV,其中 `p0_death` / `p1_death` 会区分撞墙、 自身、对手头部/身体、正面碰撞和超时等原因;对应的 `p0_death_round` / `p1_death_round` 记录死亡轮次。