简体   繁体   English

有很多成员的班级

[英]classes with a lot of members

I am attempting to create a D&D encounter simulator.我正在尝试创建一个 D&D 遭遇模拟器。 I have therefore created a class called "Actor" to emulate the behaviour of the players and the monsters.因此,我创建了一个名为“Actor”的类来模拟玩家和怪物的行为。 The problem is that while the class for the moment only have 3 member variable, as the simulation gets more accurate it will become necessary to add more member variables to best simulate the stats of the monsters and player eg strength, dexterity etc. (possibly more than 10 member variables) This leads to a constructor with a lot of parameters so the question then becomes;问题是,虽然目前该类只有 3 个成员变量,但随着模拟变得更加准确,有必要添加更多成员变量以最好地模拟怪物和玩家的统计数据,例如力量、灵巧等(可能更多超过 10 个成员变量)这导致构造函数有很多参数,所以问题就变成了; Is there a better way to organize this data, since it can all vary with every instance of the actor class?有没有更好的方法来组织这些数据,因为它会随着角色类的每个实例而变化?

Right now the user is required to type in all the states by hand, though I have plans to make file reading for monsters accessible later since monster stats only vary with monster type (dragon, skeleton etc.)现在,用户需要手动输入所有状态,但我计划稍后可以访问怪物的文件读取,因为怪物统计数据仅随怪物类型(龙、骷髅等)而变化。

Note: These stats are very important and used to calculate the outcome of every action the "Actor" class can take in the encounter.注意:这些统计数据非常重要,用于计算“演员”类在遭遇战中可以采取的每个行动的结果。

EDIT: A lot of people suggest using inheritance, but the fact is that (Monsters and Players) never have different stats, the monsters like the players are controlled by a player (The Game Master) This is a tabletop game and the simulator is supposed to help the game master balance encounter's ahead of a real game.编辑:很多人建议使用继承,但事实是(怪物和玩家)从来没有不同的统计数据,像玩家这样的怪物由玩家(游戏大师)控制这是一个桌面游戏,应该是模拟器帮助游戏大师在真正的游戏之前平衡遭遇。

Actor.h演员.h

#ifndef actor_h_
#define actor_h_

#include "dice.h"

class Actor
{
  private:
    signed int hp;
    signed int ac; // Armor Class
    signed int dmg;
    
  public:
    Actor( signed int hp, int ac, int dmg);
    ~Actor();

    signed int getHP( void );
    signed int getAC( void );
    signed int getDmg( void );
    void setHP(signed int newHP);
    void setAC(signed int newAC);
    void setDmg(signed int newDmg);

    void attack(Actor* target);
};
#endif

Actor Constructor演员构造函数

Actor::Actor(signed int hp, signed int ac, signed int dmg)
{
  this->hp = hp;
  this->ac = ac;
  this->dmg = dmg;
}
Actor::~Actor(){}

As you bring up the example of stats yourself, those could go in a当您自己提出统计数据示例时,这些数据可能会出现在

struct StatsBlock {
    int str, dex, con, /*others*/;
};

You can then either source them from static class variables or static methods:然后,您可以从静态类变量或静态方法中获取它们:

class Skeleton : public Actor {
...
public:
static inline const StatsBlock = { 13, 8, ... };
static StatsBlock rollStats() { ... );
};

As a bonus, this also gives you a central place to apply or remove effects that change the stats temporarily, like equipping a "Ring of +1 strength" or being hit with a spell like Polymorph.作为奖励,这也为您提供了一个中央位置来应用或移除暂时改变统计数据的效果,例如装备“+1 力量之戒”或被像变形术这样的法术击中。

It's a basic concept of Polymorphism in C++, and I would suggest to start from reading about it这是 C++ 中多态的基本概念,我建议从阅读它开始

You can have for example your base class Actor will contain the basic information that every entity in your emulator has (monster, player etc.)例如,您可以让基类 Actor 包含模拟器中每个实体(怪物、玩家等)的基本信息。

Then you can create a Monster and a Player class, which derive from your Actor class.然后您可以创建一个 Monster 和一个 Player 类,它们派生自您的 Actor 类。 Those will have their own unique information (tooth size, breaths under water, fly etc..)那些将有自己独特的信息(牙齿大小、水下呼吸、苍蝇等。)

If you want to dynamically create new stats for your player as the emulation goes on, I would suggest using smart pointers to hold these members for memory optimization.如果你想在模拟过程中为你的玩家动态创建新的统计数据,我建议使用智能指针来保存这些成员以进行内存优化。

If you don't want to have a parameter for each property of the stats of the actor in the constructor of the actor you can consider having a separate stats object and pass an instance of that stats to the constructor:如果您不想在 actor 的构造函数中为 actor stats 的每个属性都设置一个参数,您可以考虑拥有一个单独的 stats 对象并将该 stats 的实例传递给构造函数:

struct ActorStats {
    signed int hp;
    signed int ac; // Armor Class
    signed int dmg;
}

struct Actor {
  Actor(ActorStats stats) : stats_(std::move(stats)) {}

  signed int getHP( void );
  signed int getAC( void );
  signed int getDmg( void );
  void setHP(signed int newHP);
  void setAC(signed int newAC);
  void setDmg(signed int newDmg);

  void attack(Actor* target);

  protected:
    ActorStats stats_;
};

You could then have different strategies of creating an actor, like reading from a save file, or from a preset:然后,您可以使用不同的策略来创建角色,例如从保存文件或预设中读取:

ActorStats read_stats_from_file() {
    ActorStats stats;
    // some reading logic

    stats.hp = // value read from file

    return stats;
}

Actor create_actor() {
    ActorStats stats = read_stats_from_file();
    Actor actor(stats);

    return Actor;
}

That way you don't need to implement a getter/setter for each stats, and don't need to use friend for the functions that should initialize the stats.这样你就不需要为每个统计数据实现一个getter/setter,也不需要为应该初始化统计数据的函数使用friend But the raw values are still protected, as soon as they are passed to the Actor .但是原始值仍然受到保护,只要它们被传递给Actor

This leads to a constructor with a lot of parameters so the question then becomes;这导致构造函数有很多参数,所以问题就变成了; Is there a better way to organize this data, since it can all vary with every instance of the actor class?有没有更好的方法来组织这些数据,因为它会随着角色类的每个实例而变化?
Right now the user is required to type in all the states by hand, though I have plans to make file reading for monsters accessible later since monster stats only vary with monster type (dragon, skeleton etc.)现在,用户需要手动输入所有状态,但我计划稍后可以访问怪物的文件读取,因为怪物统计数据仅随怪物类型(龙、骷髅等)而变化。

It sounds like this question is less about how to engineer the OOP, but rather how to define all the stats for the program without it being hugely cumbersome.听起来这个问题不是关于如何设计 OOP,而是关于如何定义程序的所有统计信息而不是非常麻烦。

Reading stats from files is a good idea.从文件中读取统计信息是个好主意。 You could represent them in one or more JSON files and use Nlohmann's JSON library to read it into your program.您可以在一个或多个 JSON 文件中表示它们,并使用Nlohmann 的 JSON 库将其读入您的程序。 You'll still have to write code that says how your program should use the read JSON data, and of course you need to write the JSON in the first place---no free lunch.您仍然需要编写代码来说明您的程序应该如何使用读取的 JSON 数据,当然您首先需要编写 JSON ---没有免费的午餐。 But it could nevertheless be helpful for organizing the program.但它仍然有助于组织该计划。

Another thought: for actors like an army of orcs, or wherever there are multiple instances of the same kind, a useful approach could be to define an orc factory function that creates an orc actor and its stats.另一个想法:对于像兽人军队这样的演员,或者在有多个相同类型实例的任何地方,一个有用的方法可能是定义一个兽人工厂函数来创建一个兽人演员及其统计数据。 The factory could pseudorandomly vary speed, strength, etc. so that each orc is personalized a little different without having to manually write stats for each instance.工厂可以伪随机地改变速度、力量等,以便每个兽人的个性化都略有不同,而不必为每个实例手动编写统计数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM