-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9833831
Showing
44 changed files
with
4,339 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: Test | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Setup mdBook | ||
uses: peaceiris/actions-mdbook@v1 | ||
with: | ||
mdbook-version: 'latest' | ||
|
||
- name: Add mermaid support | ||
run: cargo install mdbook-mermaid | ||
|
||
- name: Add Katex support | ||
run: cargo install mdbook-katex | ||
|
||
- run: mdbook build | ||
|
||
- name: Deploy | ||
uses: peaceiris/actions-gh-pages@v3 | ||
if: ${{ github.ref == 'refs/heads/main' }} | ||
with: | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
publish_dir: ./book |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
book |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# 现代推箱子教程 | ||
|
||
本文将描述如何实现一个推箱子 📦, 示例代码使用 Rust 语言 🦀 编写. | ||
|
||
本文遵循 [CC-BY 4.0] 协议发布. 部分图片来源于互联网, 版权归原作者所有. | ||
|
||
[CC-BY 4.0]: <https://creativecommons.org/licenses/by/4.0/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mermaid.initialize({ startOnLoad: true, theme: 'neutral' }); |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[book] | ||
title = "现代推箱子教程" | ||
description = "本文将描述如何实现一个推箱子 📦, 示例代码使用 Rust 语言 🦀 编写." | ||
authors = ["ShenMian <sms_school@outlook.com>"] | ||
language = "zh-Hans-CN" | ||
multilingual = false | ||
src = "src" | ||
|
||
[output.html] | ||
additional-js = ["assets/mermaid.min.js", "assets/mermaid-init.js"] | ||
git-repository-url = "https://github.com/ShenMian/sokoban-tutorial" | ||
git-repository-icon = "fa-github" | ||
|
||
[preprocessor.mermaid] | ||
command = "mdbook-mermaid" | ||
|
||
[preprocessor.katex] | ||
after = ["links"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
@echo off | ||
|
||
cd %~dp0\.. || exit /b 1 | ||
|
||
git checkout --orphan empty || exit /b 1 | ||
git branch -D main || exit /b 1 | ||
git add -A || exit /b 1 | ||
git commit -m "." || exit /b 1 | ||
git push origin empty:main --force || exit /b 1 | ||
git checkout main || exit /b 1 | ||
git branch -D empty | ||
git pull origin main --allow-unrelated-histories |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/bash | ||
|
||
cd "$( cd "$( dirname "$0" )" && pwd )" || exit | ||
cd .. || exit | ||
|
||
git checkout --orphan empty || exit 1 | ||
git branch -D main || exit 1 | ||
git add -A || exit 1 | ||
git commit -m '.' || exit 1 | ||
git push origin empty:main --force || exit 1 | ||
git checkout main || exit 1 | ||
git branch -D empty | ||
git pull origin main --allow-unrelated-histories |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Summary | ||
|
||
[介绍](introduction.md) | ||
|
||
- [设计 🚧](design.md) | ||
- [关卡](level/README.md) | ||
- [表示](level/representation.md) | ||
- [构造](level/construction.md) | ||
- [标准化 🚧](level/normalization.md) | ||
- [动作]() | ||
- [求解器 🚧](solver/README.md) | ||
- [搜索策略 🚧](solver/solving_strategy.md) | ||
- [启发式函数 🚧](solver/heuristic_function.md) | ||
- [优化](solver/optimization.md) | ||
- [隧道](solver/tunnels.md) | ||
- [死锁 🚧](solver/deadlocks.md) | ||
- [割点]() | ||
- [双向搜索]() | ||
- [特征]() | ||
- [优化器]() | ||
- [资源](resources.md) | ||
- [术语表](glossary_of_terms.md) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# 设计 | ||
|
||
## 结构体设计 | ||
|
||
- `Map`: 存储地图数据. | ||
- 包含所有地图元素的数组. | ||
- 包含玩家位置, 箱子和目标位置: 方便快速读取, 否则需要遍历数组来获取相应元素的坐标. | ||
- `Actions`: 存储玩家的动作, 包括动作的类型(移动或推动), 以及方向(上下左右). | ||
- `Level`: 关卡, 包含地图和玩家动作. 可以执行或撤销动作. | ||
|
||
将 `Level` 中与地图相关的内容分离到 `Map` 中, 是为了将地图数据与关卡功能分离. 许多涉及地图的操作(例如计算两个地图之间的相似度)与关卡功能无关. | ||
|
||
> `Map` 的数组是否应该包含玩家和箱子元素? 🤔 | ||
> | ||
> - 包含: | ||
> - 在修改玩家位置或移动箱子时, 需要同步数组中的数据. 可能引入导致数据不一致的 BUG. 但因为实现十分简单, 因此引入 BUG 的可能性不大. | ||
> - 存在数据冗余, 但是冗余的数据量很小, 不至于造成显著的内存占用率变化. | ||
> - 不包含: 读取时需要判断是否与玩家或任意箱子的位置相同, 如果有就追加相关元素的枚举值. 导致读取比写入有更大的开销. 取比写入开销大违反直觉, 违背了 POLA[^POLA]. | ||
> | ||
> 综上所述, 本文倾向于在数组里包含这些元素. | ||
> `Map` 的数组应该是一维的还是二维的? 🤔 | ||
> | ||
> 由于该数组是动态数组, 二维动态数组的分配与释放需要更大的开销. 而使用一维动态数组, 内存布局会更加紧凑, 且可以提供使用二维坐标读取地图内容的关联函数. 因此使用一维数组更为合适. | ||
## 转换关系 | ||
|
||
```mermaid | ||
flowchart LR | ||
A[String] -->|XSB 格式| B[Map] | ||
A -->|LURD 格式| C[Actions] | ||
C -->|重建| B | ||
B --> D[Level] | ||
``` | ||
|
||
[^POLA]: <https://en.wikipedia.org/wiki/Principle_of_least_astonishment> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# 术语表 | ||
|
||
| 中文 | 英文 | | ||
| ----------- | ---------- | | ||
| 求解器 | solver | | ||
| 解决方案/解 | solution | | ||
| 动作 | action | | ||
| 容器[^1] | collection | | ||
|
||
[^1]: `collection` 被翻译为 "容器", 延用了 C++ 中的叫法. 不译为 "集合" 是为了防止与集合 "set" 混淆. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# 介绍 | ||
|
||
本文将描述如何实现一个推箱子 📦, 示例代码使用 Rust 语言 🦀 编写. | ||
|
||
## 推箱子的起源 | ||
|
||
推箱子在 1981 年由日本人今林宏行(いまばやし ひろゆき)所创造, 第一个版本于 1982 年 12 月发行, 名为*仓库番*, 字面意思为 "仓库管理员" 👷.[^1] 英文名为: Sokoban 或 Soukoban. | ||
|
||
<img alt="First Sokoban #15" src="assets/first_sokoban_15.png" width="50%" style="display: block; margin: 0 auto"> | ||
|
||
截至 2024 年, 最新版本推箱子(みんなの倉庫番)于 2019 年 8 月在 PlayStation 4 平台发行.[^1] | ||
|
||
<img alt="The Sokoban" src="assets/everyones_sokoban.jpg" width="70%" style="display: block; margin: 0 auto"> | ||
|
||
最新版本的推箱子在角色控制方面相较于其最初的版本并未见明显改进, 本文后续将介绍一种纯鼠标控制的角色控制方法 🖱️. | ||
|
||
## 为什么通过案例来讲解 | ||
|
||
本文以推箱子为案例, 深入浅出的描述软件开发过程. 通过案例讲解有以下目的: | ||
|
||
- 结合实例的学习可以将**知识**和**应用**结合在一起, 使读者无需被 "学这个有什么用?" 所困扰 🤔. | ||
- 提供丰富的实例. 推箱子问题本身还附带了许多子问题, 很适合作为例子使用. | ||
- 众多读者对游戏有浓厚的兴趣 🎮. | ||
|
||
## 为什么选择推箱子作为案例 | ||
|
||
之所以选择推箱子, 是因为它具有以下特点: | ||
|
||
- **规则简单**: 可以专注于实现功能, 而非理解复杂的游戏规则和机制. | ||
- **基本功能易于实现**: 如推箱子和通关判断. | ||
- **有具有挑战的高级功能**: 如纯鼠标控制, 逆推等. | ||
- **有需要深入钻研的求解器**: 用于自动求解推箱子关卡. | ||
|
||
推箱子的实现**既可以简单也可以复杂**, 读者可以根据自身的情况选择学习的深度. | ||
|
||
## 需要具备的知识 | ||
|
||
- 具备 Rust 语言的语法基础, 或熟悉一门命令式编程语言. | ||
- 有关高级功能和求解器的章节: 具备数据结构与算法的基础知识, 如 A* 搜索算法的工作原理. | ||
|
||
## 内容范围 | ||
|
||
本文将描述基本功能的具体实现方法, 高级功能的实现方法以及求解器的实现思路. | ||
但本文**不涉及**以下内容: | ||
|
||
- Rust 语言本身: 本文中出现的算法适用于其他编程语言, 但依然会涉及部分 Rust 相关内容的讲解, 如错误处理 (Rust 在这方面和其他语言不太一样), 不感兴趣的读者可以直接跳过这部分内容. | ||
- 游戏引擎: 本文中的推箱子实现并不依赖游戏引擎, 比如有的推箱子实现需要用到射线检测. | ||
- 其他推箱子变体[^2]. | ||
|
||
## 项目代码 | ||
|
||
完整的项目代码位于: | ||
|
||
- [ShenMian/soukoban](https://github.com/shenmian/soukoban): 推箱子相关算法实现. | ||
- [ShenMian/sokoban-rs](https://github.com/shenmian/sokoban-rs): 基于 Bevy 引擎的推箱子实现. | ||
|
||
## 拓展资料 | ||
|
||
推荐视频 🎥: | ||
|
||
- [【GM】火遍全球的推箱子,那些你所不知道的故事!· Bilibili](https://www.bilibili.com/video/BV1Ph41117YT): 该视频详细介绍了推箱子的历史和发展. | ||
|
||
## 版权 | ||
|
||
本文遵循 [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/) 协议发布. 部分图片来源于互联网, 版权归原作者所有. | ||
|
||
[^1]: <https://www.sokoban.jp/history.html> | ||
[^2]: <https://en.wikipedia.org/wiki/Sokoban#Variants> |
Oops, something went wrong.