C ++确定类是否可以使用对象 - 文本RPG游戏

时间:2016-12-06 19:35:11

标签: c++ inheritance

我面临以下设计问题:

TL; TD需要确定Hero(类)是否可以使用特定对象,而有许多英雄实现

我有3个Hero类的子类,每个子类都可以使用特定的项目。

对于Weapons.hpp,我有Sword,Hammer,CrossBow,Bow,Wand,Staff。

战士可以使用剑或锤子 弓箭手可以使用CrossBow或弓箭 向导可以使用工作人员或魔杖

有Hero基础课:

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);

4 个答案:

答案 0 :(得分:2)

我通过删除所有不必要的内容并将其概括为Item的概念来简化示例。武器是物品的子类,药水,魔杖,助焊剂电容器等等。 use方法执行Itemtarget所做的任何操作。武器将试图击中并伤害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使用从WeaponItem继承的通用方法来查看它是否点击target,而不知道target实际上是HugeRedDragon个实例,如果它击中指定伤害,然后执行VorpalSword检查截肢的特定事情。

所有Hero看到的都是item->use(target)

答案 1 :(得分:0)

您可以使用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 *。< / p>

或者,你可以检查每个HeroSubClass中Weapon *use()的类型,也许打印出类似&#34; Warrior不能使用Staff&#34;如果它是错误类的对象。

答案 2 :(得分:0)

您可以使用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
}

答案 3 :(得分:0)

我正考虑使用访客模式。

类似的东西:

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);
}

有关这个想法的任何建议吗?