设计模式练习题-开宝箱

题目

一个开宝箱游戏的基本描述为:游戏中有多种类型的人物(Role),如战士(Solider)、魔法师(Mage)等,主角的类型只能选择其中一种,且游戏中不再更改。游戏中还有各种宝箱(Box),如装有不同数目金钱的宝箱、装有毒物的宝箱等。当任一种类型的主角打开装有金钱的宝箱时,宝箱中的金钱会增加给主角,同时宝箱的金钱数目变成0;当战士打开装有毒物的宝箱时,战士的生命值(HP)会减少10%,但金钱(Money)增加20%;当魔法师打开装有毒物的宝箱时,魔法师的生命值(HP)会减少30%,但金钱(Money)增加40% 。
请根据上述描述,给出相应类的设计并完整实现,要求你的设计应具有良好的扩展性,如增加新角色类型及箱子种类时,不需要修改已有的设计及实现。

代码

#include <iostream>
#include <string>
#include <sstream>
#include <typeinfo>

using namespace std;

class Role;

class Box
{
protected:
  Box(int money) : money(money) {}
public:
  int money;
  virtual bool beOpenBy(Role& role) = 0;
  virtual string toString()
  {
    stringstream ss;
    ss << typeid(this).name() << "[Money:" << money << "]";
    return ss.str();
  }
};

class Role
{
protected:

  Role(int hp, int money) : hp(hp), money(money) { }
public:
  int hp, money;
  virtual bool openBox(Box& box) = 0;
  virtual string toString()
  {
    stringstream ss;
    ss << typeid(this).name() << "[HP:" << hp << ",Money:" << money << "]";
    return ss.str();
  }
};


class Solider : public Role
{
public:
  Solider() : Role(200, 50) { };
  bool openBox(Box& box)
  {
    return box.beOpenBy(*this);
  }
};


class Mage : public Role
{
public:
  Mage() : Role(100, 100) { };
  bool openBox(Box& box)
  {
    return box.beOpenBy(*this);
  }
};

/*
  宝箱名: 金钱宝箱
  特性: 提高角色的金钱
*/
class MoneyBox : public Box
{
public:
  MoneyBox() : Box(200) {};
  bool beOpenBy(Role& role)
  {
    role.money += this->money;
    this->money = 0;
    return true;
  }
};

/*
  宝箱名: 毒宝箱
  特性: 对角色造成伤害,并提高角色的金钱
*/
class PoisionBox : public Box
{
public:
  PoisionBox() : Box(0) {};
  bool beOpenBy(Role& role)
  {
    const auto& tpid = typeid(role);

    if (tpid == typeid(Solider))
    {
      role.hp *= 0.9;
      role.money *= 1.2;
      return true;
    } else if (tpid == typeid(Mage))
    {
      role.hp *= 0.7;
      role.money *= 1.4;
      return true;
    } else
    {
      return role.openBox(*this);
    }
  }
};

//新增宝箱 对所有已存在的角色进行处理
/*
  宝箱名: 剧毒宝箱
  特性: 提高对角色的伤害,并提高角色的金钱收益
*/
class VeryPoisionBox : public Box
{
public:
  VeryPoisionBox() : Box(0) {};
  bool beOpenBy(Role& role)
  {
    const auto& tpid = typeid(role);

    if (tpid == typeid(Solider))
    {
      role.hp *= 0.5;
      role.money *= 1.4;
      return true;
    } else if (tpid == typeid(Mage))
    {
      role.hp *= 0.3;
      role.money *= 1.6;
      return true;
    } else
    {
      return role.openBox(*this); //如果本宝箱无法处理该角色,则该角色在本宝箱之后添加, 所以 该角色能够处理本宝箱
    }
  }
};
//再新增角色 对所有已存在的宝箱进行处理
/*角色名:毒师
  特性:增加对毒的抗性  提高从毒宝箱中获取的金钱数,降低受到毒宝箱的伤害,但是从金钱宝箱中获取的金钱数减少
*/
class Poisoner : public Role
{
public:
  Poisoner() : Role(100, 100) { };
  bool openBox(Box& box)
  {
    const auto& tpid = typeid(box);
    if (tpid == typeid(MoneyBox))
    {
      this->money += box.money * 0.8;
      box.money = 0;
      return true;
    } else if (tpid == typeid(PoisionBox))
    {
      this->hp *= 0.9;
      this->money *= 1.6;
      return true;
    } else if (tpid == typeid(VeryPoisionBox))
    {
      this->hp *= 0.6;
      this->money *= 2.0;
      return true;
    } else
    {
      return box.beOpenBy(*this); //如果本角色无法处理该宝箱,则该宝箱在本角色之后添加, 所以 该宝箱能够处理本角色;
    }

  }
};

int main()
{
  Role& role = *new Poisoner();
  Box& pbox = *new PoisionBox();
  Box& box = *new MoneyBox();
  Box& vpbox = *new VeryPoisionBox();

  cout << role.toString() << endl;
  cout << box.toString() << endl;
  cout << pbox.toString() << endl;
  cout << vpbox.toString() << endl;

  role.openBox(box);
  role.openBox(pbox);
  role.openBox(vpbox);

  cout << role.toString() << endl;
  cout << box.toString() << endl;
  cout << pbox.toString() << endl;
  cout << vpbox.toString() << endl;

  return 0;
}

————————————————

原文链接:https://blog.csdn.net/qq_37386833/article/details/100919779

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容