c++ - 文字冒险游戏-如何区分一种元素类型以及如何构造元素类/子类?

标签 c++ game-development adventure

我是一名初学者程序员(虽然他具有C++基础知识和C++数据结构,但他具有大量与视频游戏有关的与设计相关的脚本编写经验,但几乎没有编程经验-只是诸如循环,流控制等基本知识)。和算法的类(class)在我的带领下)。我正在从事一个文本冒险的个人项目(实际上,早在很久以前我就已经在Python中写过它,然后才知道类是如何工作的-一切都是字典-太可耻了)。我正在用类在C++中对其进行“重新制作”,以摆脱仅完成家庭作业的麻烦。

我已经编写了我的播放器和房间类(这很简单,因为每个类只需要一个类)。我要讲的是物品类(物品是房间里的任何东西,例如火炬,火,标牌,容器等)。我不确定如何处理项目基类和派生类。这是我遇到的问题。

  • 我该如何以一种无知的方式辨别某项物品是否属于某种类型(我很有可能对此进行了过度思考)?
  • 例如,我设置了打印室信息功能,以便除了执行其他操作外,它还会打印 list 中每个对象的名称(即,在其中),并希望它为容器打印一些特殊的内容对象(例如其库存的内容)。
  • 第一部分很容易,因为每个项目都有一个名称,因为name属性是基础项目类的一部分。但是,容器具有 list ,这是容器子类唯一的属性。
  • 我的理解是,基于对象的类类型执行条件逻辑是一种不好的形式(因为一个人的类应该是多态的),并且我假设(也许不正确地)放置一个getHasInventory访问器虚拟函数是很奇怪和错误的在项目基类中(我的假设是基于这样的想法:将虚拟函数用于基类中的每个派生类都是疯狂的-我大约有十二个派生类-其中两个是派生类的派生类) 。
  • 如果一切正确,那么可以接受的方法是什么?一个明显的事情是在基类上添加一个itemType属性,然后执行条件逻辑,但这使我感到错误,因为这似乎只是对检查类类型解决方案的重新设计。我不确定上述假设是否正确,以及什么是好的解决方案。
  • 我应该如何构造一个或多个基类和派生类?
  • 我最初将它们编写为使得item类是基类,而其他大多数类都使用单继承(一对夫妇具有多级)。
  • 这似乎表现出一些尴尬,并且重复了我自己。例如,我想要一个标志和一个字母。标志是可读项目>不可采项目>项目。字母是可读项目>可接受项目>项目。因为它们都使用单一继承,所以我需要两个不同的可读项,一个是可以接受的,一个不是。(我知道在这种情况下,我可以使基础属性能够被接受和不被接受,但是我做到了,但这可以作为示例,因为我仍然与其他类(class)有类似的问题)。
  • 在我看来,这很讨厌,所以我再次尝试了一下,并使用多重继承和虚拟继承将它们全部实现。就我而言,这似乎更加灵活,因为我可以组成多个类的类并为我的类创建一种组件系统。
  • 这些方法之一比另一种更好吗?有第三种更好的方法吗?
  • 最佳答案

    解决问题的一种可能方法是多态。通过使用多态,您可以(例如)拥有一个describe函数,该函数在被调用时会导致该项目向玩家描述自己。您可以对use和其他常见动词执行相同的操作。

    另一种方法是实现更高级的输入解析器,该解析器可以识别对象并将动词传递给项目的某些(多态)功能,以供其自身处理。例如,每个项目都可以具有一个返回可用动词列表的函数,以及一个返回该项目的“名称”列表的函数:

    struct item
    {
        // Return a list of verbs this item reacts to
        virtual std::vector<std::string> get_verbs() = 0;
    
        // Return a list of name aliases for this item
        virtual std::vector<std::string> get_names() = 0;
    
        // Describe this items to the player
        virtual void describe(player*) = 0;
    
        // Perform a specific verb, input is the full input line
        virtual void perform_verb(std::string verb, std::string input) = 0;
    };
    
    class base_torch : public item
    {
    public:
        std::vector<std::string> get_verbs() override
        {
            return { "light", "extinguish" };
        }
    
        // Return true if the torch is lit, false otherwise
        bool is_lit();
    
        void perform_verb(std::string verb, std::string) override
        {
            if (verb == "light")
            {
                // TODO: Make the torch "lit"
            }
            else
            {
                // TODO: Make the torch "extinguished"
            }
        }
    };
    
    class long_brown_torch : public base_torch
    {
        std::vector<std::string> get_names() override
        {
            return { "long brown torch", "long torch", "brown torch", "torch" };
        }
    
        void describe(player* p) override
        {
            p->write("This is a long brown torch.");
            if (is_lit())
                p->write("The torch is burning.");
        }
    };
    

    然后,如果玩家输入light brown torch解析器浏览所有可用项(玩家 list 中的项,然后是房间中的项),获取每个项的名称列表(调用项get_names()函数)并将其与brown torch进行比较。如果找到匹配项,则解析器通过适当的参数(perform_verb)调用items item->perform_verb("light", "light brown torch")函数。

    您甚至可以修改解析器(和项)以单独处理形容词,甚至修改诸如the之类的文章,或者保存最后使用的项,以便可以使用it进行引用。

    构造不同的房间和物品很繁琐,但是一旦完成了良好的设计,仍然是微不足道的(您确实应该花一些时间来创建需求,分析需求并创 build 计)。真正困难的部分是编写一个不错的解析器。

    请注意,这只是在这种游戏中处理项目和动词的两种可能方式。还有许多其他方法,其中有很多都可以列出它们。

    关于c++ - 文字冒险游戏-如何区分一种元素类型以及如何构造元素类/子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62278098/

    相关文章:

    c++ - Ubuntu Mate 上的 WiringPi

    c# - 平铺对象位置与 MonoGame 位置不匹配

    c++ - 关于纯 ECS(实体组件系统)和更新系统的问题

    java - 单次按键即可流畅移动

    python - 在Python中,我将如何为文本冒险创建一个保存系统?

    c# - 关于基于类的文本冒险游戏设计的质疑。

    c++ - Windows 应用程序以非管理员身份运行时看到文件的旧版本而不是当前版本

    c++ - 当在另一个线程上完成工作时,有没有办法保护智能指针不在一个线程上被释放?

    c++ - 模板代理方法无法编译