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,13 +1,14 @@
|
||||
# 8.移动方向
|
||||
|
||||
<em>传统的文本冒险使用</em><em>指南针方向</em><em>进行导航。</em>
|
||||
<em>传统的文本冒险使用</em><em>[指南针方向](https://en.wikipedia.org/wiki/Cardinal_direction)</em><em>进行导航。</em>
|
||||
|
||||
例如,我们在第 6 章中绘制的地图上,玩家可能想<strong>向东</strong>移动,从田野移动到洞穴。我们可以通过给连接<strong>Cave</strong>的通道标上“east”来实现这一点。但是,我们首先需要解决两个问题。
|
||||
|
||||
1. 我们可能仍然想把这段通道称为“entrance”和“east”。但现在,一个对象只能有一个标签。
|
||||
2. 在更大的地图上,具有更多的位置和道路,标签“east”将被定义多次。到目前为止,标签在我们的游戏中是全球独一无二的,没有重复项。
|
||||
|
||||
思考题:你能否想出解决办法?
|
||||
::: warning 🤔 思考题:你能否想出解决办法?
|
||||
:::
|
||||
|
||||
这些问题同样适用于其他对象,而不仅仅是通道。
|
||||
|
||||
@@ -17,11 +18,11 @@
|
||||
|
||||
这立即将我们带到了解析器的第三个问题:
|
||||
|
||||
1. 一个标签只能是一个单词;“ sliver coin”这是俩单词,他不接受啊
|
||||
1. 一个标签只能是一个单词;“sliver coin”这是俩单词,他不接受啊
|
||||
|
||||
所有三个问题都将在本章中解决,从问题#1 开始。它通过为每个对象提供一个标签列表来解决,而不仅仅是一个标签。
|
||||
|
||||
# object.h
|
||||
## object.h
|
||||
|
||||
```c
|
||||
typedef struct object {
|
||||
@@ -47,7 +48,7 @@ extern OBJECT objs[];
|
||||
#define endOfObjs (objs + 10)
|
||||
```
|
||||
|
||||
# object.c
|
||||
## object.c
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
@@ -63,7 +64,7 @@ static const char *tags6[] = {"east", "entrance", NULL};
|
||||
static const char *tags7[] = {"west", "exit", NULL};
|
||||
static const char *tags8[] = {"west", "north", "south", "forest", NULL};
|
||||
static const char *tags9[] = {"east", "north", "south", "rock", NULL};
|
||||
//我们不固定标签长度,在结束的时候用NULL来标记
|
||||
//我们不固定标签长度,在结束的时候用 NULL 来标记
|
||||
OBJECT objs[] = {
|
||||
{"an open field" , tags0, NULL , NULL },
|
||||
{"a little cave" , tags1, NULL , NULL },
|
||||
@@ -75,22 +76,22 @@ OBJECT objs[] = {
|
||||
{"an exit to the west" , tags7, cave , field },
|
||||
{"dense forest all around" , tags8, field, NULL },
|
||||
{"solid rock all around" , tags9, cave , NULL }
|
||||
//我们用NULL来阻绝进入一个你不知道的地方
|
||||
//我们用 NULL 来阻绝进入一个你不知道的地方
|
||||
};
|
||||
```
|
||||
|
||||
当然,要让这个改动生效,我们还需要调整<em>noun.c</em>中的<em>objectHasTag</em>函数。
|
||||
|
||||
<em>同时,我们将让函数 getVisible</em>和<em>getPossession</em> 告知玩家他必须更具体的选择你到底是银币还是金币 ,而不是随机选择任何一个对象。
|
||||
<em>同时,我们将让函数 getVisible</em>和<em>getPossession</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);
|
||||
```
|
||||
|
||||
# <strong>noun.c</strong>
|
||||
## <strong>noun.c</strong>
|
||||
|
||||
```c
|
||||
#include <stdbool.h>
|
||||
@@ -107,7 +108,7 @@ static bool objectHasTag(OBJECT *obj, const char *noun)
|
||||
for (tag = obj->tags; *tag != NULL; tag++)
|
||||
{
|
||||
if (strcmp(*tag, noun) == 0) return true;
|
||||
}//扫描对象的tag列表
|
||||
}//扫描对象的 tag 列表
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -187,9 +188,9 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
|
||||
}
|
||||
```
|
||||
|
||||
问题 #3 可以通过从函数<em>parseAndExecute</em>中删除一个 [空格](http://en.wikipedia.org/wiki/Space_(punctuation))字符来解决(下面的第 10 行)。这个解决方案远非完美('silver' 和 'coin' 之间的双空格是大咩的),但直到我们在第 13 章中让自己成为一个更好的解析器之前。
|
||||
问题 #3 可以通过从函数<em>parseAndExecute</em>中删除一个 [空格](http://en.wikipedia.org/wiki/Space_(punctuation))字符来解决(下面的第 10 行)。这个解决方案远非完美('silver' 和 'coin' 之间的双空格是打咩的),但直到我们在第 13 章中让自己成为一个更好的解析器之前。
|
||||
|
||||
# parsexec.c
|
||||
## parsexec.c
|
||||
|
||||
```c
|
||||
#include <stdbool.h>
|
||||
@@ -249,4 +250,5 @@ bool parseAndExecute(char *input)
|
||||
|
||||
现在对象数组 ( <em>object.c</em> ) 开始在多个维度上增长(特别是在引入多个标签的情况下),我们需要一种使其更易于维护的方法。
|
||||
|
||||
猜猜看该怎么办?
|
||||
::: warning 🤔 猜猜看该怎么办?
|
||||
:::
|
||||
|
||||
Reference in New Issue
Block a user