首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >口袋妖怪娱乐的好设计

口袋妖怪娱乐的好设计
EN

Software Engineering用户
提问于 2013-11-17 08:34:06
回答 5查看 5.5K关注 0票数 2

我目前正在进行一个小组项目,以便在Java中重新创建最初的Pokemon黄色版本。我们刚刚开始计划它,但是我们现在已经画出的设计方法是有一个抽象的口袋妖怪类,并且有151个类(原始口袋妖怪的计数)来扩展它,每个类都是不同的口袋妖怪。每个类将能够存储数据,如ID、名称、口袋妖怪的类型(即:rock/water/fire/等等),以及它可以使用和学习的动作。为口袋妖怪创建151个类似乎有点麻烦,但它似乎也是限制耦合的好方法。就设计而言,这是一个很好的方法去做它,如果不是,有什么更好的方法去做呢?

EN

回答 5

Software Engineering用户

回答已采纳

发布于 2013-11-17 11:10:42

您并没有真正解释为什么您的小组认为生成151个类是个好主意(希望如此),因为“减少耦合”还没有真正的意义,因为您没有设计或代码,因此也没有耦合。

每个类将能够存储数据,如ID、名称、口袋妖怪的类型(即:rock/water/fire/等等),以及它可以使用和学习的动作。

将该句子中的“类”改为“实例”,您就会明白为什么只需要创建一个Pokemon类:它们都共享相同的属性。派生类应该添加或实现该派生所特有的属性(和/或方法)。

如果您将ElementTypeMovePokemonBase的属性定义为:

代码语言:javascript
复制
enum ElementType
{
    Fire = 1,
    Water = 2,
    Grass = 4,
    Rock = 8,
}

class Move
{
    int ID;
    string Name;
    ElementType ElementType;
    int BaseDamage;
}

class PokemonBase
{
    int ID;
    string Name;
    ElementType ElementTypes;
    List<Move> Moves;

    decimal HitPointsPerLevel;
    decimal AttackPointsPerLevel;
}

那么,您的各种实例仅在这些属性中的内容不同。您的类和代码不应该关心这个问题。具有Fire类型的口袋妖怪可以与类型为水的口袋妖怪存储在完全相同的类中:它们只具有不同的ElementTypes属性值。

现在,您可以使用它们的属性和移动来填充Pokemon实例的列表,例如,以您喜欢的格式加载文本文件或从数据库读取。

在加载口袋妖怪时,您可以解决所有这些问题。在数据源中,您可以存储其他属性,在“它可以使用和学习的移动”的情况下,这些属性可以是一个关系表(或等效的平面文本),您可以在其中将Pokemon.IDMove.IDLevel连接到对方(如果内存正确的话,他们将学习达到预设级别的新步骤),将其存储在口袋妖怪类中的列表或字典属性中。

或者,在设计的时候,你认为你需要一个不同的类来为每个精灵实现不同的战斗系统。您不必这样做,因为通过组合各种属性,您可以为每个实例赋予其独特的属性。

当然,当您意识到实际上有两种类型的口袋妖怪时,问题就开始了:一种是游戏中可能出现的所有口袋妖怪的“蓝图”,另一种是玩家携带的一个实际的口袋妖怪,它有一个级别、HitPoints等,所有属性都取决于或通过该级别计算,或者基于“在游戏中”这个事实。可以在派生类中实现这些属性:

代码语言:javascript
复制
class Pokemon : PokemonBase
{
    int Level;
    int MaxHitPoints;
    int HitPoints;

    // Stats, for example
    int Attack { get { return Level * base.AttackPointsPerLevel } };
    int Defense;

    // This method directly applies the attack results to the incoming Pokemon, by reference.
    int Attack(Pokemon other, Move attack)
    {       
        int damageDone = (this.Attack * attack.BaseDamage) - defender.Defense;

        // TODO: http://bulbapedia.bulbagarden.net/wiki/Type_chart
        decimal modifier = CalculateEffectiveness(other, attack);
        damageDone *= modifier;

        other.HitPoints -= damageDone;      

        return damageDone;
    }
}

所有Pokemon实例都可以使用它,而无需派生任何内容。关键是对类和方法进行建模,以便您想要对每个类和方法执行的操作可以应用于所有类型的组合。例如,您还可以向List<DamageOverTimeAttack>添加一个Pokemon,以实现应该保持活动几个回合的攻击,并在Attack()方法中处理它。

现在,当玩家遇到一个新的口袋妖怪时,您可能需要从一个工厂创建它:

代码语言:javascript
复制
class PokemonFactory
{
    List<PokemonBase> _allPokemon;

    Pokemon GetPokemon(id, level)
    {
        blueprint = _allPokemon.Find(id);

        return new Pokemon
        {
            ID = blueprint.ID,
            Name = blueprint.Name,
            ...
            Level = level,
            ...
        };
    }       
}
票数 6
EN

Software Engineering用户

发布于 2013-11-17 09:46:34

不同的pokemons应该在代码中公开不同的API吗?你应该先分析一下这个。

它们的ID、名称和类型可以存储在成员中。现在你可以说他们有不同的能力。所以每一种能力都应该是一种方法。但你错了。这样做会阻止您在管理战斗时编写简单的代码。

你应该在一个单独的类中抽象出一种能力。它可以用它的成本和效果来定义。那么每个生物都有一个能力列表。您的151个pokemons是在服务方法或配置文件中定义的。在编写特性时,代码不应该关心传递什么样类型的口袋妖怪。

151类建模是一个巨大的复杂成本。很可能,您必须使用反射来检查与某个特定类相关的数据。这将是对java类系统的误用。

票数 2
EN

Software Engineering用户

发布于 2013-11-17 09:01:06

我相信,如果你有一个基本的口袋妖怪类型,它可能更容易从基类中只派生出火、水、电类型,以限制所需的不同类的数量。由此,您可以设置口袋妖怪类型之间的关系,而不需要太多麻烦,例如。火胜水、草、弱、电等。

从这里,您可能有一个数据库或JSON/XML文件,它存储每个pokemom、ID、name的所有统计数据,以及它是从哪个演化来的。这种格式绝对可以帮助对数据进行分组和分类,而不需要太多开销。一旦程序按顺序读取JSON/XML文件,程序初始化后,每个pokemon类型类都可以提取数据。一旦您在文件存储中设置了所有的状态,那么整个过程就可以自动化了。从那里,访问每个口袋妖怪应该是简单的!

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/218680

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档