文本冒险游戏-如何区分一种物品类型和另一种,以及如何构造物品类/子类? 我是一个初学者程序员(他有一系列与设计相关的脚本经验,但是很少有编程经验——所以只需要基本的东西,比如循环、流控制等等),虽然我有一个C++基础和C++的数据结构和算法的课程。我正在做一个文本冒险的个人项目(其实我早在很久以前就已经用Python写过了,在我学会类的工作原理之前——一切都是一本字典——所以这是可耻的)。我在用C++来“重做”它,让我们摆脱只做作业的习惯。
我已经编写了我的player和room类(很简单,因为每个类只需要一个类)。我进入了物品类(物品是房间里的任何东西,如手电筒、火、标志、容器等)。我不确定如何接近项基类和派生类。以下是我遇到的问题文本冒险游戏-如何区分一种物品类型和另一种,以及如何构造物品类/子类? 我是一个初学者程序员(他有一系列与设计相关的脚本经验,但是很少有编程经验——所以只需要基本的东西,比如循环、流控制等等),虽然我有一个C++基础和C++的数据结构和算法的课程。我正在做一个文本冒险的个人项目(其实我早在很久以前就已经用Python写过了,在我学会类的工作原理之前——一切都是一本字典——所以这是可耻的)。我在用C++来“重做”它,让我们摆脱只做作业的习惯。,c++,game-development,adventure,C++,Game Development,Adventure,我已经编写了我的player和room类(很简单,因为每个类只需要一个类)。我进入了物品类(物品是房间里的任何东西,如手电筒、火、标志、容器等)。我不确定如何接近项基类和派生类。以下是我遇到的问题 我如何以一种非狗屎的方式判断一件物品是否属于某种类型(我很有可能是想得太多了) 例如,我设置了“打印室信息”功能,以便它除了可以执行其他操作外,还可以打印其库存中每个对象的名称(即库存内部),并且我希望它打印容器对象的特殊内容(例如库存内容) 第一部分很简单,因为每个项都有一个名称,因为name属性
- 例如,我设置了“打印室信息”功能,以便它除了可以执行其他操作外,还可以打印其库存中每个对象的名称(即库存内部),并且我希望它打印容器对象的特殊内容(例如库存内容)李>
- 第一部分很简单,因为每个项都有一个名称,因为name属性是基本项类的一部分。不过,容器有一个清单,这是容器子类特有的属性李>
- 我的理解是,基于对象的类类型执行条件逻辑是不好的(因为一个人的类应该是多态的),我假设(可能是错误的)将getHasInventory访问器虚拟函数放在item基类中是奇怪和错误的(我在这里的假设是基于这样的想法:将每个派生类的虚拟函数都放在基类中是疯狂的——我有十几个派生类——其中有两个是派生类的派生类)
- 如果这些都是正确的,那么什么是可以接受的方法呢?一个显而易见的方法是向基添加itemType属性,然后执行条件逻辑,但这让我觉得是错误的,因为这似乎只是检查类类型解决方案的重新蒙皮。我不确定上述假设是否正确,以及什么是好的解决方案可能是
- 我最初编写它们是为了让item类成为基类,而大多数其他类使用单一继承(除了一对具有多级继承的类)
- 这似乎有点尴尬,重复了我自己。例如,我想要一个符号和一个字母。符号是可读项>不可提取项>项。字母是可读项>可提取项>项。因为它们都使用单一继承,我需要两个不同的可读项,一个可提取,一个不可提取(我知道在本例中我可以将takeable和untakeable设置为base的属性,我确实这样做了,但这只是一个例子,因为我在其他类中仍然存在类似的问题)
- 这对我来说似乎很棘手,所以我又尝试了一次,并使用多重继承&虚拟继承来实现它们。在我的例子中,这似乎更灵活,因为我可以组合多个类的类,并为我的类创建一种组件系统
- 这些方法中有一种比另一种好吗?有第三种方法更好吗
解决问题的一种可能方法是多态性。通过使用多态性,您可以(例如)拥有一个
descripe
函数,当调用该函数时,该函数将引导项目向玩家描述自身。您可以对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.");
}
};
struct项
{
//返回此项响应的谓词列表
虚拟std::vector get_动词()=0;
//返回此项的名称别名列表
虚拟std::vector get_names()=0;
//向玩家描述这些物品
虚拟空描述(玩家*)=0;
//执行特定动词,输入是完整的输入行
虚拟void执行动词(std::string动词,std::string输入)=0;
};
基本类火炬:公共物品
{
公众:
std::vector get_动词()覆盖
{
返回{“灯”,“熄灭”};
}
//如果火炬点亮,则返回true,否则返回false
bool是_lit();
void执行动词(std::string动词,std::string)重写
{
如果(动词==“轻”)
{
//TODO:使火炬“点燃”
}
其他的
{
//TODO:使火炬“熄灭”
}
}
};
班长\棕色\火炬:公共基地\火炬
{
std::vector get_names()覆盖
{
返回{“长棕色火炬”、“长火炬”、“棕色火炬”、“火炬”};
}
无效描述(玩家*p)覆盖
{
p->写(“这是一个长长的棕色火炬。”);
如果(是_lit())
p->写(“火炬在燃烧”);
}
};
然后,如果玩家输入,例如浅棕色手电筒
解析器检查所有可用项目(玩家清单中的项目,然后是房间中的项目),获取每个项目名称列表(调用项目get_names()
函数)并将其与brown torch
进行比较。如果找到匹配项,解析器将调用itemsperform\u verb
函数传递适当的参数(item-