C++ 确定类是否可以使用对象 - 文本 RPG 游戏
C++ Determine if class can use an object - text RPG game
>我面临以下设计问题:
TL;TD需要确定Hero(类)是否可以在有许多英雄实现的情况下使用特定对象
我有 3 个英雄类的子类,每个子类都可以使用特定的物品。
对于武器.hpp,我有剑,锤子,十字弓,弓,魔杖,法杖。
战士可以使用剑或锤子 弓箭手可以使用弩或弓 向导可以使用法杖或魔杖
有英雄基类:
class Hero: public Entity{
public:
Hero(std::string name, Gender gender, double damage, Point2d* location);
~Hero();
virtual void move(int x, int y);
virtual void damage(Entity* other); // Override
virtual bool use(Potion* _potion);
virtual bool use(Weapon* _weapon) = 0;
virtual bool use(ShieldArmor* _shieldArmor) = 0;
virtual bool use(BodyArmor* _bodyArmor) = 0;
private:
std::string name;
Gender gender;
Weapon* weapon;
ShieldArmor* shield_armor;
BodyArmor* body_armor;
};
这是 武器:
class Weapon: public Item{
public:
Weapon(double damage, Point2d* location);
virtual ~Weapon();
virtual double getDamage() const;
virtual const Point2d* getLocation() const;
virtual const std::string toString() const;
private:
Point2d* location;
double damage;
};
在游戏的主屏幕中,我需要确定 Hero *h 是否可以在可能的情况下使用特定物品而无需向下施放。
所以我可以像这样使用它:
Hero *h;
Weapon * i;
// do something assign values
h->use(i);
我通过删除所有不必要的内容并推广到Item
的概念来简化示例。武器是物品的子类,药水、魔杖、通量电容器等等。use
方法执行Item
对target
执行的任何操作。武器会试图击中并伤害target
.治疗药水可以治愈target
。磁通电容器要么及时发送target
,要么用1.21千兆瓦的功率消除从中删除的咒骂。
但一切都是通过Item
的镜头看到的.调用类不知道项目是什么、做什么或它对target
做了什么。target
甚至不知道上面用了什么,他们只是感觉到效果。没有人知道一个简单的通用接口之外的其他对象。
class Item
{
public:
enum types
{
whole lot of types go here.
They are fairly broad categories, like knife, sword, two handed sword,
healing potion, wand, etc.
};
types getType()
{
return type;
}
virtual bool use(Entity * target) = 0;
private:
types type;
};
class Hero: public Entity{
public:
Hero(std::set<Item::type> & usable): usableItems(usable)
~Hero();
bool use(Item* item,
Entity * target)
{
// this is the magic. If the item's type is in the list of usable items,
// the item is used on the target. They exact type of item or target
// is not known. Polymorphism will take care of everything from here
if (usableItems.find(item->getType()) != usableItems.end())
{
return item->use(target);
}
return false;
}
private:
std::set<Item::type> & usableItems;
};
关键是主要类非常愚蠢。它们只是为更详细的对象提供一个框架来完成详细的工作。VorpalSword
使用从Weapon
和Item
继承的通用方法来查看它是否击中了target
,不知道target
实际上是一个HugeRedDragon
实例,如果它击中了,则分配伤害,然后做VorpalSword
所做的特定事情,例如检查掉落的肢体。
而英雄看到的只是item->use(target)
.
您可以使用dynamic_cast<>()
来确定 Hero 指针的类型,如下所示:
Hero *h;
Weapon * i;
// do something assign values
if(dynamic_cast<HeroSubClass> != nullptr)
h->use(i);
其中HeroSubClass
是您要检查的特定Hero
子类(Warrior
等)。如果你的Hero *
不是指向类HeroSubClass
对象的指针,dynamic_cast
将返回nullptr
,如果是,它将返回一个HeroSubClass *
。
或者,您可以检查每个 HeroSubClass 在use()
内Weapon *
的类型,如果它是错误职业的对象,则可以打印出类似"战士无法使用法杖"之类的内容。
您可以使用enum
值来定义武器和英雄的特定类型。
enum class HERO_TYPE{
WARRIOR,
ARCHER,
WIZARD
}
class Hero: public Entity{
public:
Hero( std::string name, Gender gender, double damage, Point2d* location, HERO_TYPE type );
~Hero();
virtual void move(int x, int y);
virtual void damage(Entity* other); // Override
virtual bool use(Potion* _potion);
virtual bool use(Weapon* _weapon) = 0;
virtual bool use(ShieldArmor* _shieldArmor) = 0;
virtual bool use(BodyArmor* _bodyArmor) = 0;
private:
std::string name;
Gender gender;
Weapon* weapon;
ShieldArmor* shield_armor;
BodyArmor* body_armor;
HERO_TYPE type; //define in subclasses.
};
并对武器做同样的事情。
enum class WEAPON_TYPE{
SWORD,
CROSSBOW,
WAND
}
class Weapon: public Item{
public:
Weapon(double damage, Point2d* location, WEAPON_TYPE type);
virtual ~Weapon();
virtual double getDamage() const;
virtual const Point2d* getLocation() const;
virtual const std::string toString() const;
WEAPON_TYPE get_type() { return this->type; }//getter
private:
Point2d* location;
double damage;
WEAPON_TYPE type;
};
现在您可以指定英雄职业的武器。
void Hero::use(Weapon *i){
if(!checkWeapon(i->get_type())) return;
//...code...
}
bool Hero::checkWeapon(WEAPON_TYPE t){
switch(this->type){
case HERO_TYPE::WARRIOR:{
if(t == WEAPON_TYPE::SWORD)
return true;
}break;
case HERO_TYPE::ARCHER:{
if(t == WEAPON_TYPE::CROSSBOW)
return true;
}break;
//..all cases..
}
return false;//no hero-weapon matching
}
我正在考虑使用访客模式。
像这样:
Hero * h;
Item * i;
Visitor v;
// Assign some values
h.accept(v,i);
然后访客看起来像:
visit(sword *p, warrior * w){
w.use(p);
}
visit(wand *p, wizard * w){
w.use(p);
}
visit(bow *p, archer * w){
w.use(p);
}
关于这个想法有什么建议吗?
- 如何从文本文件C++制作对象?
- C++ - 确定 const char* 是指向字符串文本对象还是动态对象
- 遍历对象向量,并找到与从文本文件中提取的对象匹配的变量
- 使用空格分隔符从文本文件将对象读入数组
- 为什么使用 C++ 中的类对象写入文件中的数据以非文本格式存储?
- 从文本文件中读取对象
- 如果给定了文本样式,如何获取特定文本的 QSize 对象
- 有没有办法基于文本文件动态创建对象?
- 如何设计对象以不同方式设置文本格式
- 为什么<string>字符串对象需要 #include 而不是字符串文本?
- 尝试从文本文件读取到对象数组
- 对由文本实例化的对象的类引用
- 无法将对象的值写入文本文件 C++
- 在基于文本的游戏中,如何将对象放置在房间内?
- 如何在文本文件中逐行读取并填充指向对象数组的指针
- 我想从文本文件中获取信息并将该信息分配给类对象
- OpenCV程序的输出在未检测到文本对象时不给出0
- 设计具有变体字段的文本类型类,其中可以存储一个或三个对象
- 如何解析文本文件并使用构造函数中的文件输入来创建对象的容器
- C++ 确定类是否可以使用对象 - 文本 RPG 游戏