many, many chore
This commit is contained in:
FallenYing
2023-07-28 09:30:17 +08:00
parent b043fd1d05
commit f501a6b993
33 changed files with 453 additions and 453 deletions

View File

@@ -1,12 +1,12 @@
# 12.开启关闭
在上一章中,我们使用 "条件 "函数来使对象消失。当然,还有一个更简单的方法来实现同样的目的:只要清除对象的位置属性就可以了!
在上一章中,我们使用 "条件 "函数来使对象消失。当然,还有一个更简单的方法来实现同样的目的:只要清除对象的位置属性就可以了
洞口是一个典型的例子,条件函数在那里工作得特别好。这是因为入口受到其他对象(守卫和银币)中的属性的影响;我们可以使用函数使得所有的逻辑都能保持一致。
让我们举一个更直接的例子。假设山洞有一扇门通向一个密室。只是一个简单的门洞,玩家可以打开和关闭。就像前一章一样,我们将使用两个对象来表示这个通道;一个表示打开的门,另一个表示门关闭时。
```
```txt
- backroom
description "a backroom"
tags "backroom"
@@ -28,11 +28,12 @@
textGo "The door is closed.\n"
```
思考题:尝试自己用 C 语言实现
::: warning 🤔 思考题:尝试自己用 C 语言实现
:::
自然,门也应该能从另一侧进入。
```
```txt
- openDoorToCave
description "an open door to the north"
tags "north", "door", "doorway"
@@ -111,7 +112,8 @@ else
}
```
思考题:你能不能仿照上面的代码实现 close 功能?
::: warning 🤔 思考题:你能不能仿照上面的代码实现 close 功能?
:::
为了使事情稍微复杂一些,我们可以在门上或盒子上加一把锁。这需要(至少)三个相互排斥的对象;每个可能的状态都有一个:打开、关闭和锁定。但是我们仍然可以使用同一个函数来交换对象的位置。例如,这里是如何解锁一个上锁的盒子;反之亦然。
@@ -132,15 +134,17 @@ else if (obj == lockedBox)
显然,代码的行数与游戏中的门(以及盒子和其他可以打开的物体)的数量成正比。因此,如果你的游戏有不止几扇门,那么选择一个更通用的解决方案是个好主意。顺便说一下,这对每一个命令都是适用的:当它涉及到许多物体时,尽量写通用代码;但当你处理一两个特殊情况时,就坚持使用直接的、专门的代码。
思考题:我们可以使用什么方法来解决这个问题?
::: warning 🤔 思考题:
我们可以使用什么方法来解决这个问题?
提示C++ 中的模板功能(这只是一种选择)
下面我们将揭晓答案
:::
通用代码通常带有数据驱动的方法。换句话说,我们需要向我们的对象结构添加一个或多个属性。在这种特殊情况下,我们将为我们希望支持的每个命令添加一个函数指针:打开、关闭、锁定和解锁。
# object.txt
## object.txt
```c
#include <stdbool.h>
@@ -354,7 +358,7 @@ extern OBJECT objs[];
为了避免重复的代码,我们这次特意没有使用匿名函数。相反,我们将在一个单独的模块中实现必要的逻辑。函数 swapLocations 也在其中,这不过是一个稍微扩展的版本,它也会向用户输出反馈。
# toggle.h
## toggle.h
```c
extern void cannotBeOpened(void);
@@ -376,7 +380,7 @@ extern void toggleBox(void);
extern void toggleBoxLock(void);
```
# toggle.c
## toggle.c
```c
#include <stdbool.h>
@@ -439,7 +443,7 @@ void toggleBoxLock(void)
正如前面所宣布的,打开、关闭、锁定和解锁这四个命令的实现是完全通用的。
# openclose.h
## openclose.h
```c
extern void executeOpen(const char *noun);
@@ -448,7 +452,7 @@ extern void executeLock(const char *noun);
extern void executeUnlock(const char *noun);
```
# openclose.c
## openclose.c
```c
#include <stdbool.h>
@@ -478,17 +482,18 @@ void executeUnlock(const char *noun)
{
OBJECT *obj = reachableObject("what you want to unlock", noun);
if (obj != NULL) (*obj->unlock)();
}
```
上面,我们使用了一个通用函数 reachableObject 来处理不在这里的对象;其实现见下文。这样,我们就不必把同样的代码写四遍(每个执行函数写一遍)。更多的命令将在第 15 章中加入;这些命令将受益于同样的函数。
# reach.h
## reach.h
```c
extern OBJECT *reachableObject(const char *intention, const char *noun);
```
# reach.c
## reach.c
```c
#include <stdbool.h>
@@ -526,7 +531,7 @@ OBJECT *reachableObject(const char *intention, const char *noun)
同样,我们也要对 parsexec.c 进行补充
# parsexec.c
## parsexec.c
```c
#include <stdbool.h>