2

程序背景:用户只能输入string两个词中的一个 - 一个动词和一个名词。我将此字符串标记为 avectortokens[0]与 avector允许的动词和tokens[1]avector允许的名词进行比较。

现在,我正在尝试找到一种方法,只允许对某些名词执行某些动词。例如,写“take book”会给出一条消息(或其他),说它是允许的,但写“take door”则不会。到目前为止,我已经为每个可能的动词创建了一个class带有bool值的对象(例如,在 中class Object,我可以创建一个Object bookfor whichm_take = truefalsefor an Object door)。

但是,我无法将这些对象与用户输入关联起来。例如,我希望能够做这样的事情: 1)用户输入“动词名词”,它作为和
进入标记向量。 2)程序检查输入是否包含可接受的单词(单独)。 3) 考虑作为检索对象上可行操作的布尔值的函数,程序检索并且如果是,则执行(例如)。这样我就可以在我的 中只有一个循环,它可以被所有合法的动词和名词使用,而无需制作无限的 , 等列表,手动考虑每个选项。tokens[0]tokens[1]

getstat()tokens[1].getstat(tokens[0])truetokens[0].tokens[1]()book.take()ifmain()ifelse if

对不起,如果这完全令人困惑。我知道不可能使用变量作为对象名称,但我确信有更好的方法来做到这一点,而不是在考虑动词和名词的每一个混合和匹配的循环中循环。我目前正在尝试每个 3 个,但是一旦我开始工作,我计划扩展它,如果我必须对每个可能的动词和名词进行多次硬编码,那么跟踪每一个变化将是一场噩梦源代码。(另外,很抱歉没有发布整个源 - 这是一个非常长的文件!)感谢您提供正确方向的任何帮助/提示!

4

3 回答 3

2

您可以对这类东西使用运行时多态性,无论是使用virtual方法还是 C++11std::function和 lambda。

您显然必须重新设计您的“令牌”系统。


虚拟方法示例:

struct Object
{ 
    virtual void onTake() { }
    virtual void onOpen() { }
};

struct Door : public Object 
{
    bool open{false};
    void onTake() override { say("I can't take the door!"); }
    void onOpen() override { say("The door is now open."); open = true; }
};

struct Book : public Object
{
    void onTake() override { say("I put the book in my backpack."); }
    void onOpen() override { say("I open the book. All the pages are blank."); }
};

C++11 lambda 示例:

struct Object
{ 
    std::function<void()> onTake, onOpen;
};

struct Door : public Object 
{
    bool open{false};
    Door() 
    {
        onTake = []{ say("I can't take the door!"); };
        onOpen = []{ say("The door is now open."); open = true; };
    }
};

struct Book : public Object
{
    Book() 
    {
        onTake = []{ say("I put the book in my backpack."); };
        onOpen = []{ say("I open the book. All the pages are blank."); };
    }
};

// You can also avoid creating new classes
Object bananaPrototype; 
bool eaten{false};
bananaPrototype.onTake = []{ say("I put the banana in my backpack."); };
bananaPrototype.onOpen = [eaten] mutable 
{ say("I eat the banana. Yum."); eaten = true; };
于 2013-09-29T14:38:53.843 回答
0

正如你所说,tokens[0].tokens[1]()没有做你想做的事 - 程序运行时函数和变量的名称不可用。

您可以尝试使用地图。objects可以是带有对象名称键的映射。这些值 ( objects[token[0]]) 反过来将是其他映射,它们将是执行您想要的功能 ( objects[token[0]][token[1]])。

这是一个例子:

#include <unordered_map>
#include <string>
#include <iostream>

using namespace std;

void read_fn()
{
    cout << "You read the book";
}

int main()
{
    unordered_map <string, unordered_map <string, void (*)()>> lookup;

    unordered_map <string, void (*)()> book_lookup;

    book_lookup["read"] = read_fn;
    lookup["book"] = book_lookup;

    lookup["book"]["read"]();
}
于 2013-09-29T14:44:30.500 回答
0

在没有看到代码的这种不平凡的情况下很难给出建议,但据我了解,您最好考虑放弃硬编码方法,即 book.take(). 尝试编写更通用的代码,至少类似于book.action(actions::kTake).

于 2013-09-29T14:43:38.653 回答