chore: add 3.4.6.2
chore: add 3.4.6.3
chore: add 3.4.6.4
chore: add 3.4.6.5
chore: add 3.4.6.6
chore: add 3.4.6.7
chore: add 3.4.6.8
chore: add 3.4.6.9
chore: add 3.4.6.10
docs: add 3.6.5.1
This commit is contained in:
FallenYing
2023-07-27 23:15:47 +08:00
parent b9449a0d88
commit b043fd1d05
14 changed files with 535 additions and 89 deletions

View File

@@ -1,6 +1,6 @@
# 7.增大距离
<em>一个典型的冒险包含许多谜题。</em><em>众所周知Infocom</em><em>的冒险很难完成。解决每个难题可能需要数周甚至数月的反复试验。</em>
<em>一个典型的冒险包含许多谜题。</em><em>众所周知,[Infocom](https://en.wikipedia.org/wiki/Infocom)</em><em>的冒险很难完成。解决每个难题可能需要数周甚至数月的反复试验。</em>
<em>当玩家操纵角色失败后,如果只是返回“你</em><em>不能这么操作</em><em>”来回应玩家</em><em>,会很 nt很没意思</em><em>。</em>
@@ -10,7 +10,7 @@
<em>冒险游戏至少应该做的是解释为什么玩家的命令无法完成:“你不能这样做,因为......”这有助于使虚拟世界更具说服力,故事更可信,游戏更有趣。</em>
我们已经付出了相当大的努力让游戏解释<strong>为什么</strong>某些命令是无效的。只需看看<em>名词.cinventory.clocation.c</em><em>move.c</em>中的许多<em>printf</em>调用。 但随着游戏变得越来越复杂,这正成为一个相当大的负担。我们需要一种更结构化的方法来检测和处理错误情况。这就是我们在本章中将要讨论的内容。
我们已经付出了相当大的努力让游戏解释<strong>为什么</strong>某些命令是无效的。只需看看<em>名词.cinventory.clocation.c</em><em>move.c</em>中的许多<em>printf</em>调用。但随着游戏变得越来越复杂,这正成为一个相当大的负担。我们需要一种更结构化的方法来检测和处理错误情况。这就是我们在本章中将要讨论的内容。
大多数命令对一个或多个对象进行操作,例如:
@@ -64,7 +64,8 @@ typedef enum {
} DISTANCE;
```
typedef 以及枚举类 enum 之前有接触过吗?没有接触过的话就去学习一下吧。
::: warning 💡 typedef 以及枚举类 enum 之前有接触过吗?没有接触过的话就去学习一下吧。
:::
在最右边的列中,我们为每个情况提出了一个满足条件。通过一些重新洗牌,我们可以很容易地将其转换为计算对象“距离”的函数(从玩家的角度来看):
@@ -84,9 +85,11 @@ DISTANCE getDistance(OBJECT *from, OBJECT *to)
}
```
思考题:你是否有其他方法实现这个功能?
::: warning 🤔 思考题:
你是否有其他方法实现这个功能?
注:自行实验即可
:::
就这样!我们可以调用此函数并对其返回值进行比较。例如,我们在 noun<em>.c</em>中有以下代码:
@@ -110,7 +113,7 @@ else if (!(getDistance(player, obj) == distSelf ||
getDistance(player, obj) == distHere ||
getDistance(player, obj) == distOverthere ||
getDistance(player, obj) == distHeldContained ||
getDistance(player, obj) == distHereContained)
getDistance(player, obj) == distHereContained))
```
这可以简化为:
@@ -119,13 +122,14 @@ else if (!(getDistance(player, obj) == distSelf ||
else if (getDistance(player, obj) >= distNotHere)
```
尝试理解一下这样做的意义
::: warning 🤔 尝试理解一下这样做的意义
:::
这只是一个例子,让你对这个概念有所了解;您将在下面找到<em>noun.c</em>的实际实现,看起来略有不同。
是时候把事情落实到位了。枚举 <em>DISTANCE</em> 和函数 <em>getDistance</em> 的定义被添加到 <em>misc.h</em> 和 <em>misc.c</em> 中,因为我们将在多个模块中使用它们。
# misc.h
## misc.h
```c
typedef enum {
@@ -150,7 +154,7 @@ extern OBJECT *actorHere(void);
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdbool.h>
@@ -226,7 +230,7 @@ int listObjectsAtLocation(OBJECT *location)
注意isHolding 这个函数之后我们将在各个地方使用
# location.h
## location.h
```c
extern void executeLook(const char *noun);
@@ -235,7 +239,7 @@ extern void executeGo(const char *noun);
在函数 <em>executeGo</em> 中,我们可以用检查距离来替换大多数 <em>if</em> 条件。
# location.c
## location.c
```c
#include <stdbool.h>
@@ -290,11 +294,12 @@ void executeGo(const char *noun)
}
```
思考题:你能否为 switch 函数增加更多 case 来完善判断条件?
::: warning 🤔 思考题:你能否为 switch 函数增加更多 case 来完善判断条件?
:::
函数 <em>executeGet</em> 也是如此。
# <strong>inventory.h</strong>
## <strong>inventory.h</strong>
```c
extern void executeGet(const char *noun);
@@ -304,7 +309,7 @@ extern void executeGive(const char *noun);
extern void executeInventory(void);
```
# <strong>inventory.c</strong>
## <strong>inventory.c</strong>
```c
#include <stdbool.h>
@@ -369,14 +374,14 @@ void executeInventory(void)
最后,我们将调整 noun<em>.c</em>中的约束。我们正在向函数<em>getObject</em>添加两个参数,以便找到特定名词的匹配项,同时忽略任何被认为不存在的对象。这将在下一章中得到真正的回报,我们将在下一章中介绍具有相同标签的不同对象。
# noun.h
## noun.h
```c
extern OBJECT *getVisibleconst char *intention const char *noun;
extern OBJECT *getPossessionOBJECT *from const char *verb const char *noun;
```
# noun.c
## noun.c
```c
#include <stdbool.h>
@@ -455,7 +460,8 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
}
```
思考题:你能理解什么时候加 const什么时候不用吗
::: warning 🤔 思考题:你能理解什么时候加 const什么时候不用吗
:::
在本章中,<em>距离</em>的概念主要用于在游戏可以给用户的不同响应之间进行选择。但是,距离的好处并不局限于<strong>输出</strong>端;它可以同样很好地用于在<strong>输入</strong>端进行改进。在下一章中,我们将使用距离来提高对用户输入的名词的识别。