Я разрабатываю ролевую игру и меня блокируют настройки 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 ответ
Хочу отметить, что это (T > A > W > T) — очень интересная проблема.
При этом позвольте мне внести свой вклад.
Фактически
superзвонок необходим, когда ваш классextendsдругой класс. Почему так? Потому что это помогает вам вызывать родительские классыconstructorи правильно инициализировать родительский класс.Переходя на
GameLogicкласс, который у вас есть мерзавец но не просил для обзора.Функции
checkActа такжеbattleфункции выполняют некоторую работу на основеact. Теперь этоif-elseлестницу можно улучшить, изменив это наswitchблокировать. Возможно, вы захотите очистить это.switch(act) { case 1: ... break; ... default: ... break; }Теперь последняя функция
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Теперь окончательные значения, оставшиеся во всех наборах, будут вашим результатом.
Надеюсь это поможет.
