update
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:
@@ -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>名词.c,inventory.c,location.c</em>,<em>move.c</em>中的许多<em>printf</em>调用。 但随着游戏变得越来越复杂,这正成为一个相当大的负担。我们需要一种更结构化的方法来检测和处理错误情况。这就是我们在本章中将要讨论的内容。
|
||||
我们已经付出了相当大的努力让游戏解释<strong>为什么</strong>某些命令是无效的。只需看看<em>名词.c,inventory.c,location.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 *getVisible(const char *intention, const char *noun);
|
||||
extern OBJECT *getPossession(OBJECT *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>端进行改进。在下一章中,我们将使用距离来提高对用户输入的名词的识别。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user