вычисления для значений, которые соответствуют указанным критериям в ограниченном пространстве поиска

Я разрабатываю ролевую игру и меня блокируют настройки HP (очки здоровья / очки здоровья / сила здоровья), атаки и защиты для персонажей — Assassin, Tank и Warrior

Я хотел бы выяснить значения, чтобы Убийца гарантированно победил Воина, в то время как Воин гарантированно победит Танка, тогда как Танк гарантированно победит Убийцу.

Итак, я написал лабораторную работу, чтобы решить эту головоломку.

Вот часть Character.java, остальное — это просто автоматически сгенерированные сеттеры и геттеры.

private int maxHp, hp, attack, defense, level;
private int place, xp, gold;
private String name;

public void setHp(int hp) {
    if (hp>maxHp){
        this.hp = maxHp;
    } else {
        if(hp<0){
            this.hp = 0;
        } else {
            this.hp = hp;
        }
    }
}

public Character(String name, int maxHp, int attack, int defense){
    this(name, maxHp, attack, defense, 0, 0, 1);
}

public Character(String name, int maxHp, int attack, int defense, int xp, int gold, int level) {
//        super(); // Is it necessary to call super() here?
    this.name = name;
    this.maxHp = maxHp;
    this.hp = maxHp;
    this.attack = attack;
    this.defense = defense;
    this.xp = xp;
    this.gold = gold;
    this.level = level;
}

public String toString(){
    return name + "'s maxHP: " + maxHp + " Attack: " + attack + " Defense: " + defense;
}

В Util класс — это просто сокращение для System.out.println()

public class Util {
    public static void pln(){
        System.out.println();
    }
    public static void pln(Object obj) {
        System.out.println(obj);
    }
    public static void pln(int value) {
        System.out.println(value);
    }
}

LabMain выполняет расчет, содержащий многослойный цикл.

class LabMain {
    final static int MINHP = 1;
    final static int MAXHP = 100;
    final static int MINATTACK = 1;
    final static int MINDEFENSE = 0;

    public static boolean isBattleFinished(Character player, Character opponent,
            int dmgDealt, int dmgTook) {

        // the player will never win
        // as they cannot deal any damage to their opponent
        if (dmgDealt <= 0) {
            player.setHp(0);
            return true;
        }

        if (dmgTook < 0)
            dmgTook = 0;

        opponent.setHp(opponent.getHp() - dmgDealt);
        player.setHp(player.getHp() - dmgTook);

        if (player.getHp() <= 0) {
            return true;
        } else if (opponent.getHp() <= 0) {
            return true;
        }

        return false;
    }

    public static int didTheyWin(Character player, Character opponent){
        int dmgDealt = player.getAttack() - opponent.getDefense();
        int dmgTook = opponent.getAttack() - player.getDefense();
        int round = 0;
        boolean isFinished = true;

        do {
            round++;
            isFinished = isBattleFinished(player, opponent, dmgDealt, dmgTook);
        } while (round<MAXHP && !isFinished);

        if (player.getHp() > 0) {
            return round;
        }

        return 0;
    }

    static void lab() {
        for(int assassinMaxHP = MINHP; assassinMaxHP < MAXHP; assassinMaxHP+=MINHP){
            Util.pln("assassinMaxHP: " + assassinMaxHP);
            for(int assassinAttack = MINATTACK; assassinAttack < MAXHP; assassinAttack+=MINHP){
                for(int assassinDefense = MINDEFENSE; assassinDefense < MAXHP; assassinDefense+=MINHP){
                    Util.pln("assassinDefense: " + assassinDefense);
                    for(int warriorMaxHP = MINHP; warriorMaxHP < MAXHP; warriorMaxHP+=MINHP){
                        Util.pln("warriorMaxHP: " + warriorMaxHP);
                        for(int warriorAttack = MINATTACK; warriorAttack < MAXHP; warriorAttack+=MINHP){
                            Util.pln( "assassinAttack: " + assassinAttack +
                                    " assassinDefense:" + assassinDefense +
                                    " warriorMaxHP: " + warriorMaxHP +
                                    " warriorAttack: " + warriorAttack);
                            for(int warriorDefense = MINDEFENSE; warriorDefense < MAXHP; warriorDefense+=MINHP){
                                for(int tankMaxHP = MINHP; tankMaxHP < MAXHP; tankMaxHP+=MINHP){
                                    for(int tankAttack = MINATTACK; tankAttack < MAXHP; tankAttack+=MINHP){
                                        for(int tankDefense = MINDEFENSE; tankDefense < MAXHP; tankDefense+=MINHP){
                                            Character assassin1 = new Character("A", assassinMaxHP, assassinAttack, assassinDefense);
                                            Character warrior1 = new Character("W", warriorMaxHP, warriorAttack, warriorDefense);
                                            if(didTheyWin(assassin1, warrior1)>0){
                                                Character warrior2 = new Character("W", warriorMaxHP, warriorAttack, warriorDefense);
                                                Character tank2 = new Character("T", tankMaxHP, tankAttack, tankDefense);
                                                if(didTheyWin(warrior2, tank2)>0){
                                                    Character tank3 = new Character("T", tankMaxHP, tankAttack, tankDefense);
                                                    Character assassin3 = new Character("A", assassinMaxHP, assassinAttack, assassinDefense);
                                                    if(didTheyWin(tank3, assassin3)>0){
                                                        Util.pln("- - -");
                                                        Util.pln(assassin1);
                                                        Util.pln(warrior1);
                                                        Util.pln(tank2);
                                                        Util.pln("- - -");
                                                        System.exit(0);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        lab();
    }
}

Я поставил полный код на https://github.com/albert10jp/javamud

Вот первая находка

A's maxHP: 1 Attack: 1 Defense: 1
W's maxHP: 5 Attack: 1 Defense: 0
T's maxHP: 2 Attack: 2 Defense: 0

Хотя W больше похож на Tank, а T больше на Warrior 🙂

Пожалуйста, не обращайте внимания на кучу Util.pln внутри lab() временно, что является индикатором того, что мой код не находится в бесконечном цикле, и я работаю над его улучшением.

Вопросов:

1.Есть ли более элегантный способ, при котором мне не нужно делать так много слоев петель?

2. нужно ли звонить super() в конструкторе Character?

Также приветствуются любые другие комментарии и предложения.

1 ответ
1

Хочу отметить, что это (T > A > W > T) — очень интересная проблема.

При этом позвольте мне внести свой вклад.

  1. Фактически super звонок необходим, когда ваш класс extends другой класс. Почему так? Потому что это помогает вам вызывать родительские классы constructor и правильно инициализировать родительский класс.

  2. Переходя на GameLogic класс, который у вас есть мерзавец но не просил для обзора.

    Функции checkAct а также battle функции выполняют некоторую работу на основе act. Теперь это if-else лестницу можно улучшить, изменив это на switch блокировать. Возможно, вы захотите очистить это.

    switch(act) {
        case 1:
            ...
            break;
        ...
        default:
            ...
            break;
    }
    
  3. Теперь последняя функция lab. Это ненужное зацикливание на баке, если if(didTheyWin(assassin1, warrior1)>0) ложно, т.е. вы можете пропустить что угодно tank ценности, которые вы получаете.

    Оригинал:

    for (assassin)
        for (warrior)
            for (tank)
                if (assassin > warrior)
                    if (warrior > tank)
                        if (tank > assassin)
                            exit
    

    становится:

    for (assassin)
        for (warrior)
            if (assassin > warrior)
                for (tank)
                    if (warrior > tank)
                        if (tank > assassin)
                            exit
    

    ломая проблему еще больше:

    for (assassin)
        for (warrior)
            if (assassin > warrior)
                collect in set of assassin and warrior
    
    for (warrior)
        if (warrior not in set warrior)     // ignore warriors and don't bother for tank
            continue
        for (tank)
            if (warrior > tank)
                collect in set tank
            else
                remove from set warrior     // this is not desired.
    
    for (tank)
        if (tank not in set tank)           // ignore tanks and don't bother for assassin
            continue
        for (assassin)
            if (assassin not in set assassin)   // ignore assassin
                if (tank > assassin)
                    exit / continue
                else
                    remove from set assassin    // this is not desired
    

    Теперь окончательные значения, оставшиеся во всех наборах, будут вашим результатом.

Надеюсь это поможет.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *