类 有很多成员
classes with a lot of members
我正在尝试创建一个 D&D 遭遇模拟器。
因此,我创建了一个名为“Actor”的 class 来模拟玩家和怪物的行为。问题是,虽然 class 目前只有 3 个成员变量,但随着模拟变得更加准确,将有必要添加更多成员变量以最好地模拟怪物和玩家的统计数据,例如力量、灵巧度等(可能超过10个成员变量)
这导致构造函数有很多参数,所以问题就变成了;有没有更好的方法来组织这些数据,因为它会随着演员的每个实例而变化 class?
现在,用户需要手动输入所有状态,但我计划稍后访问怪物的文件读取,因为怪物统计数据仅随怪物类型(龙、骷髅等)变化
注意:这些统计数据非常重要,用于计算“演员”class 在遭遇中可以采取的每个动作的结果。
编辑:
很多人建议使用继承,但事实是(怪物和玩家)从来没有不同的统计数据,像玩家这样的怪物是由玩家控制的(游戏大师)这是一个桌面游戏,模拟器应该有帮助游戏大师的平衡性遭遇领先于真正的游戏。
Actor.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构造函数
Actor::Actor(signed int hp, signed int ac, signed int dmg)
{
this->hp = hp;
this->ac = ac;
this->dmg = dmg;
}
Actor::~Actor(){}
当你自己举出统计数据的例子时,这些可以放在
struct StatsBlock {
int str, dex, con, /*others*/;
};
然后您可以从静态 class 变量或静态方法中获取它们:
class Skeleton : public Actor {
...
public:
static inline const StatsBlock = { 13, 8, ... };
static StatsBlock rollStats() { ... );
};
作为奖励,这还为您提供了一个中心位置来应用或移除暂时改变统计数据的效果,例如装备“+1 力量戒指”或被变形术等法术击中。
这是C++中多态的一个基本概念,建议从阅读开始
例如,您可以拥有您的基础 class Actor 将包含模拟器中每个实体(怪物、玩家等)的基本信息
然后您可以创建一个 Monster 和一个 Player class,它们派生自您的 Actor class。那些将有自己独特的信息(牙齿大小、水下呼吸、飞行等。)
如果您想在模拟过程中为您的播放器动态创建新的统计数据,我建议使用智能指针来保存这些成员以进行内存优化。
如果您不想在 actor 的构造函数中为每个 属性 的 actor 统计数据设置一个参数,您可以考虑使用一个单独的统计对象并将该统计数据的实例传递给构造函数:
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_;
};
然后您可以采用不同的策略来创建演员,例如从保存文件或预设中读取:
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;
}
这样您就不需要为每个统计数据实现 getter/setter,也不需要对应该初始化统计数据的函数使用 friend
。但是原始值仍然受到保护,只要它们被传递给 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.)
听起来这个问题不是关于如何设计 OOP,而是关于如何定义程序的所有统计信息而不是非常麻烦。
从文件中读取统计信息是个好主意。您可以在一个或多个 JSON 文件中表示它们,并使用 Nlohmann's JSON library 将其读入您的程序。您仍然需要编写代码来说明您的程序应该如何使用读取的 JSON 数据,当然您首先需要编写 JSON——天下没有免费的午餐。但它仍然有助于组织程序。
另一个想法:对于像兽人军队这样的演员,或者任何有多个同类实例的地方,一个有用的方法可能是定义一个兽人 factory function 来创建一个兽人演员及其统计数据。工厂可以伪随机地改变速度、力量等,这样每个兽人的个性化都有点不同,而不必为每个实例手动写入统计数据。
我正在尝试创建一个 D&D 遭遇模拟器。 因此,我创建了一个名为“Actor”的 class 来模拟玩家和怪物的行为。问题是,虽然 class 目前只有 3 个成员变量,但随着模拟变得更加准确,将有必要添加更多成员变量以最好地模拟怪物和玩家的统计数据,例如力量、灵巧度等(可能超过10个成员变量) 这导致构造函数有很多参数,所以问题就变成了;有没有更好的方法来组织这些数据,因为它会随着演员的每个实例而变化 class?
现在,用户需要手动输入所有状态,但我计划稍后访问怪物的文件读取,因为怪物统计数据仅随怪物类型(龙、骷髅等)变化
注意:这些统计数据非常重要,用于计算“演员”class 在遭遇中可以采取的每个动作的结果。
编辑: 很多人建议使用继承,但事实是(怪物和玩家)从来没有不同的统计数据,像玩家这样的怪物是由玩家控制的(游戏大师)这是一个桌面游戏,模拟器应该有帮助游戏大师的平衡性遭遇领先于真正的游戏。
Actor.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构造函数
Actor::Actor(signed int hp, signed int ac, signed int dmg)
{
this->hp = hp;
this->ac = ac;
this->dmg = dmg;
}
Actor::~Actor(){}
当你自己举出统计数据的例子时,这些可以放在
struct StatsBlock {
int str, dex, con, /*others*/;
};
然后您可以从静态 class 变量或静态方法中获取它们:
class Skeleton : public Actor {
...
public:
static inline const StatsBlock = { 13, 8, ... };
static StatsBlock rollStats() { ... );
};
作为奖励,这还为您提供了一个中心位置来应用或移除暂时改变统计数据的效果,例如装备“+1 力量戒指”或被变形术等法术击中。
这是C++中多态的一个基本概念,建议从阅读开始
例如,您可以拥有您的基础 class Actor 将包含模拟器中每个实体(怪物、玩家等)的基本信息
然后您可以创建一个 Monster 和一个 Player class,它们派生自您的 Actor class。那些将有自己独特的信息(牙齿大小、水下呼吸、飞行等。)
如果您想在模拟过程中为您的播放器动态创建新的统计数据,我建议使用智能指针来保存这些成员以进行内存优化。
如果您不想在 actor 的构造函数中为每个 属性 的 actor 统计数据设置一个参数,您可以考虑使用一个单独的统计对象并将该统计数据的实例传递给构造函数:
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_;
};
然后您可以采用不同的策略来创建演员,例如从保存文件或预设中读取:
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;
}
这样您就不需要为每个统计数据实现 getter/setter,也不需要对应该初始化统计数据的函数使用 friend
。但是原始值仍然受到保护,只要它们被传递给 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.)
听起来这个问题不是关于如何设计 OOP,而是关于如何定义程序的所有统计信息而不是非常麻烦。
从文件中读取统计信息是个好主意。您可以在一个或多个 JSON 文件中表示它们,并使用 Nlohmann's JSON library 将其读入您的程序。您仍然需要编写代码来说明您的程序应该如何使用读取的 JSON 数据,当然您首先需要编写 JSON——天下没有免费的午餐。但它仍然有助于组织程序。
另一个想法:对于像兽人军队这样的演员,或者任何有多个同类实例的地方,一个有用的方法可能是定义一个兽人 factory function 来创建一个兽人演员及其统计数据。工厂可以伪随机地改变速度、力量等,这样每个兽人的个性化都有点不同,而不必为每个实例手动写入统计数据。