update
many, many chore
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user