Java 嵌套的if/else、开关或更有效的RPG战斗?

Java 嵌套的if/else、开关或更有效的RPG战斗?,java,android,multidimensional-array,switch-statement,nested-statement,Java,Android,Multidimensional Array,Switch Statement,Nested Statement,我正在用java为android手机开发一个基于turn的RPG,目前我正试图找出如何处理具有额外变量的攻击。例如,当目标有燃烧效果时,我想让火焰攻击额外造成10%的伤害。我有点不确定如何以一种有效的方式来做这件事,一种允许将来添加到我的状态/攻击系统中的方式 以下是我对如何做到这一点的想法: 一系列if/else语句或开关 switch (status) { case burned: if (type == fire) { damage = damage * 1.1;

我正在用java为android手机开发一个基于turn的RPG,目前我正试图找出如何处理具有额外变量的攻击。例如,当目标有燃烧效果时,我想让火焰攻击额外造成10%的伤害。我有点不确定如何以一种有效的方式来做这件事,一种允许将来添加到我的状态/攻击系统中的方式

以下是我对如何做到这一点的想法:

  • 一系列if/else语句或开关

    switch (status) {
    case burned:
        if (type == fire) {
            damage = damage * 1.1;
        }
        break;
    case frozen:
        if (type == ice) {
            damage = damage * 2;
        }
        break;
    }
    
    如果每个状态有许多可能的结果,我也可以使用嵌套开关

  • 使用二维数组,其中
    x
    值为状态,
    y
    值为攻击或类型。当您检查
    [x][y]
    时,它会为攻击中发生的更改返回一个数值

          Burned   Frozen
    
    Fire  [1.1]    [1]
    
    Ice   [1]      [2]
    
  • 虽然这两种方法目前看来都很好,但我不确定它在未来是否会奏效。现在,我当然可以使用改变伤害数量的组合,但是对于那些具有非数值效果的攻击,我不能简单地返回一个值并将我的伤害乘以该值,那该怎么办呢

    是否有可能生成某种代码来表示以下情况:

    burned = 1 in first position, frozen = 2 fire attack = f in 2nd position, ice = i damage mod is in the 3rd position 在第一个位置燃烧=1,冻结=2 第二位置火力攻击=f,冰攻击=i 损坏模式位于第3位置
    因此,对烧毁的敌人进行火力攻击将是
    1-f-1.1

    您应该尝试使用多态性

    对于开关/if ELSE 创建一个表示攻击的接口,并让它声明一个方法:

    public interface Attack {
        double doAttack(double baseDamage);
    }
    
    然后创建实现此接口的类:

    public class FireAttack implements Attack {
        double doAttack(double baseDamage){
            return 1.1 * baseDamage;
        }
    }
    
    public class IceAttack implements Attack {
        double doAttack(double baseDamage){
            return 2 * baseDamage;
        }
    }
    
    然后,不要在代码中使用switch语句,而是执行以下操作:

    public class Player {
        private Attack mAttack;
    
        // Somewhere in your code, you setup something like
        void setFireWeapon(){
            mAttack = new FireAttack();
        }
    
        // This is where the attack is taken care of
        double inflictDamage() {
            return mAttack.doAttack();
        }
    }
    
    这允许您在将来实施任何您可能希望的新类型的攻击,并简单地将
    attack mAttack
    分配给接口
    attack
    的新实现。这是一个简单的例子,如果您愿意,您可以做一些比
    baseDamage*aDouble
    更强大的事情

    对于状态(已燃烧/已冻结) 有很多方法可以实现冻结等状态。首先,您可以使用我上面解释的相同模式

    除了拥有
    Attack mAttack
    成员之外,您还可以添加类似的逻辑,使用
    HealthStatus mHealthStatus
    或您喜欢的任何名称。然后,调用
    increateddamage()
    会将
    mAttack
    对象重定向到
    mHealthStatus
    对象

    然后,
    HealthStatus
    类将再次成为一个接口

    public interface HealthStatus {
        double considerAttack(Attack anAttack);
    }
    
    将有不同国家的实施:

    public class NormalStatus implements HealthStatus{
        double considerAttack(Attack anAttack){
            return anAttack.doAttack(); // No change here
        }
    }
    
    public class FrozenStatus implements HealthStatus{
        double considerAttack(Attack anAttack){
            return 0; // Can't attack when froxen
        }
    }
    
    public class BurnedStatus implements HealthStatus{
        double considerAttack(Attack anAttack){
            return anAttack.doAttack() * 2.0; // Get berserk when on fire!
        }
    }
    
    您也可以使用其他模式。我建议您看看设计模式,它可以解决您所面临的问题

    • 参见状态模式
    • 参见战略模式
    • 参见访客模式

    仅举几个例子。

    安东尼格走上了正确的道路。这个问题的一般解决方案是使用策略设计模式

    战略

    动机

    当类只在行为上有所不同时,存在一些常见情况。对于这种情况,最好将算法隔离在单独的类中,以便能够在运行时选择不同的算法

    意图

    定义一系列算法,封装每一种算法,并使其可互换。该策略允许算法独立于使用它的客户端而变化

    实施

    还可以查看以下链接


    你的思维似乎过于线性。使用面向对象的原则来设计游戏。为扩展通用攻击的攻击创建类

    public abstract class Attack{
        protected String attackName;
        protected Double damage;
    
        public Attack(){
            attackName = "Standard";
            damage = 1.0;
        }
    
        public Double getDamage(){
            return damage;
        }
    
        public String getAttackName(){
            return attackName;
        }
    }
    
    然后扩展:

    public class FireStorm extends Attack{
        public FireStorm(String attackName, Double damage){
            this.attackName = attackName;
            this.damage = damage;
        }
    
        @Override
        public Double getDamage(Enemy target){
            if(target.hasBurnEffect()){
                damage *= 2.0;
            } else {
                damage = super.getDamage();
            }
    
            return damage;
        }
    }
    

    我真的不太了解你游戏中的内容范围,所以我不能让它更具描述性。但是,如果你想让你的游戏像你建议的那样灵活和可扩展,那么你就需要使用继承和其他面向对象编程的原则。

    switch
    在你必须用于Android应用程序的java级别上不起作用(必须是int,不能是字符串,但可以将静态变量设置为值并使用该值)@willmer:你的问题有点含糊不清。我理解你的问题,但它与游戏开发方法更相关,更适合游戏开发者网站。这是否意味着对于我在游戏中遇到的每一次攻击,我都会将其编码为攻击的新子类?我目前有一个名为attack with variable的类例如名称、描述、能力和速度。我有一个SQLite数据库,它按名称搜索攻击,并返回与这些变量对应的值。然后在类中我调用attack.doAttack(enemyType type),它检查类型(即fire vs water)并返回损坏。我不想为每次移动都使用一个类,而是想为我的移动重用相同的模板并插入值。这是一种低效的方法吗?