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

Я пытаюсь создать симуляцию большой битвы между популяцией покемонов. В качестве примера я буду использовать двух покемонов, названных pokemon1 и pokemon2. Я хочу, чтобы программа работала следующим образом:

  • pokemon1 и pokemon2 будут сравниваться на основе их CombatScore, который представляет собой оценку, основанную на их основных атрибутах, таких как скорость, атака, защита и т. д.
  • pokemon1 и pokemon2 будут случайным образом объединены в пары друг с другом и сравнены.
  • если покемон1 имеет более высокий боевой счет, чем покемон2, то покемон1 переходит в следующий раунд (и удаляется из общей популяции и помещается в «победоносную» популяцию), а покемон2 удаляется из общей популяции и добавляется в «побежденную» популяцию .
  • Затем pokemon1 получает некоторые атрибуты, основанные на чертах pokemon2.
  • однако, если покемон2 (побежденный) является легендарным, они должны проиграть в общей сложности три раза, прежде чем они, наконец, будут добавлены к побежденному населению.
  • если pokemon1 (победитель) не был легендарным, но выиграл три раза, он становится легендарным и, следовательно, должен трижды проиграть, прежде чем он будет добавлен к побежденному населению.

Раунды повторяются с меньшим и меньшим числом победителей, пока не останется только один победитель.

Я создал цикл do-while, который будет случайным образом извлекать двух покемонов из популяции и сравнивать их на основе ряда различных условий, используя ветки if-else:

  1. легендарный покемон2 побеждает легендарный покемон1
  2. покемон2 побеждает легендарного покемона1
  3. легендарный покемон2 побеждает покемон1
  4. покемон2 лучше покемон1

И наоборот. Проблема, с которой я сталкиваюсь, заключается в следующем: большую часть времени программа работает без ошибок, и раунд 1 завершен. Все сражения записываются в файл pokemon.txt, где четко указывается, кто победил. Однако иногда программа начинает работать и остается в рабочем состоянии. Когда я пойду проверить файл .txt, он перестанет писать в середине предложения примерно в том же месте (около строки 275).

А пока я просто хочу провести первый раунд. Вот код, который запускает этот симулятор:

  do {
        Pokemon pokemon1;
        Pokemon pokemon2;
        pokemon1 = population.get((int) (Math.random() * population.size()));
        do {
            pokemon2 = population.get((int) (Math.random() * population.size()));
        } while (pokemon1.getId() == pokemon2.getId());


        if (pokemon2.getCombatScore() > pokemon1.getCombatScore()
                && pokemon2.isLegendary() && pokemon1.isLegendary()) {
            bufferedWriter.write("The legendary " + pokemon2.getName() + " defeats the legendary " +
                    pokemon1.getName() + " with a combat score of " + pokemon2.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon2.incAttack(pokemon1.getCombatScore());
            pokemon2.incDefense(pokemon1.getCombatScore());
            pokemon2.addVict();

            victorious.add(pokemon2);
            population.remove(pokemon2);

            pokemon1.addLoss();

            if (pokemon1.numLoss == 3) {
                defeated.add(pokemon1);
                population.remove(pokemon1);
            }
        }

        else if (pokemon2.getCombatScore() > pokemon1.getCombatScore()
                && pokemon1.isLegendary()) {
            bufferedWriter.write(pokemon2.getName() + " defeats the legendary " +
                    pokemon1.getName() + " with a combat score of " + pokemon2.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon2.incAttack(pokemon1.getCombatScore());
            pokemon2.incDefense(pokemon1.getCombatScore());

            pokemon2.addVict();
            if (pokemon2.numVict == 3) {
                bufferedWriter.write(pokemon2.getName() + " has become legendary!");
            }

            victorious.add(pokemon2);
            population.remove(pokemon2);

            pokemon1.addLoss();
            if (pokemon1.numLoss == 3) {
                defeated.add(pokemon1);
                population.remove(pokemon1);
            }
        }

        else if (pokemon2.getCombatScore() > pokemon1.getCombatScore()
                && pokemon2.isLegendary()) {
            bufferedWriter.write("The legendary " + pokemon2.getName() + " defeats " +
                    pokemon1.getName() + " with a combat score of " + pokemon2.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon2.incAttack(pokemon1.getCombatScore());
            pokemon2.incDefense(pokemon1.getCombatScore());
            pokemon2.addVict();

            victorious.add(pokemon2);
            population.remove(pokemon2);

            pokemon1.addLoss();

            defeated.add(pokemon1);
            population.remove(pokemon1);
        }
        else if (pokemon2.getCombatScore() > pokemon1.getCombatScore()) {
            bufferedWriter.write(pokemon2.getName() + " defeats " +
                    pokemon1.getName() + " with a combat score of " + pokemon2.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon2.incAttack(pokemon1.getCombatScore());
            pokemon2.incDefense(pokemon1.getCombatScore());

            pokemon2.addVict();
            if (pokemon2.numVict == 3) {
                bufferedWriter.write(pokemon2.getName() + " has become legendary!");
            }

            victorious.add(pokemon2);
            population.remove(pokemon2);

            pokemon1.addLoss();

            defeated.add(pokemon1);
            population.remove(pokemon1);
        }
        else if (pokemon1.getCombatScore() > pokemon2.getCombatScore()
                && pokemon2.isLegendary() && pokemon1.isLegendary()) {
            bufferedWriter.write("The legendary " + pokemon1.getName() + " defeats the legendary " +
                    pokemon2.getName() + " with a combat score of " + pokemon1.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon1.incAttack(pokemon2.getCombatScore());
            pokemon1.incDefense(pokemon2.getCombatScore());
            pokemon1.addVict();

            victorious.add(pokemon1);
            population.remove(pokemon1);

            pokemon2.addLoss();

            if (pokemon2.numLoss == 3) {
                defeated.add(pokemon2);
                population.remove(pokemon2);
            }
        }

        else if (pokemon1.getCombatScore() > pokemon2.getCombatScore()
                && pokemon2.isLegendary()) {
            bufferedWriter.write(pokemon1.getName() + " defeats the legendary " +
                    pokemon2.getName() + " with a combat score of " + pokemon1.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon1.incAttack(pokemon2.getCombatScore());
            pokemon1.incDefense(pokemon2.getCombatScore());

            pokemon1.addVict();
            if (pokemon1.numVict == 3) {
                bufferedWriter.write(pokemon1.getName() + " has become legendary!");
            }

            victorious.add(pokemon1);
            population.remove(pokemon1);

            pokemon2.addLoss();
            if (pokemon2.numLoss == 3) {
                defeated.add(pokemon2);
                population.remove(pokemon2);
            }
        }

        else if (pokemon1.getCombatScore() > pokemon2.getCombatScore()
                && pokemon1.isLegendary()) {
            bufferedWriter.write("The legendary " + pokemon1.getName() + " defeats " +
                    pokemon2.getName() + " with a combat score of " + pokemon1.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon1.incAttack(pokemon2.getCombatScore());
            pokemon1.incDefense(pokemon2.getCombatScore());
            pokemon1.addVict();

            victorious.add(pokemon1);
            population.remove(pokemon1);

            pokemon2.addLoss();

            defeated.add(pokemon2);
            population.remove(pokemon2);
        }
        else {
            bufferedWriter.write(pokemon1.getName() + " defeats " +
                    pokemon2.getName() + " with a combat score of " + pokemon1.getCombatScore() + "!");
            bufferedWriter.newLine();

            /* pokemon2 gains xp from winning */
            pokemon1.incAttack(pokemon2.getCombatScore());
            pokemon1.incDefense(pokemon2.getCombatScore());

            pokemon1.addVict();
            if (pokemon1.numVict == 3) {
                bufferedWriter.write(pokemon1.getName() + " has become legendary!");
            }

            victorious.add(pokemon1);
            population.remove(pokemon1);

            pokemon2.addLoss();

            defeated.add(pokemon2);
            population.remove(pokemon2);
        }

    }while (population.size() != 0);

А вот пример скриншота файла .txt, когда он работает «навсегда»:

272 Stoutland defeats Loudred with a combat score of 5415!
273 Croconaw defeats Electrike with a combat score of 3272!
274 Rapidash defeats Meditite with a combat score of 7390!
275 Jynx defeat

Я пробовал отлаживать и выполнять каждое условие, чтобы убедиться, что они работают. Я довольно уверен, что они все делают. Проблема в другом? Это проблема, с которой он сталкивается, когда в популяции нечетное количество покемонов? Любые предложения будут ценны.


person Community    schedule 16.02.2017    source источник
comment
Чтобы помочь вам с отладкой, я предлагаю вам добавлять bufferedWriter.flush() после каждой записи в него. Это может привести к прозрению. В настоящее время в буферизованном модуле записи все еще хранится некоторый текст, что затрудняет понимание того, к чему все идет.   -  person WW.    schedule 16.02.2017
comment
Кроме того, я бы с подозрением отнесся к вашему взгляду, связанному с math.random. Может быть, поместите туда отладочную печать, чтобы увидеть, не застряло ли оно.   -  person WW.    schedule 16.02.2017
comment
Добавил оператор отладки в мой цикл while, и я думаю, что проблема в этом. Теперь, когда кажется, что программа работает вечно, похоже, что она как-то связана с логикой внутри цикла while. Возможно, проблема в том, что он ищет другого покемона, когда в общей популяции остался только один?   -  person    schedule 16.02.2017


Ответы (1)


Проблема в том, что при выборе обоих претендентов на бой вы попадаете в цикл, который никогда не выйдет:

pokemon1 = population.get((int) (Math.random() * population.size()));
do {
    pokemon2 = population.get((int) (Math.random() * population.size()));
} while (pokemon1.getId() == pokemon2.getId());

Это кажется прекрасным, но что произойдет, если в популяции будет только один покемон? Он никогда не выберет второй и никогда не выйдет из цикла.

Что касается того, почему он перестает писать в середине предложения, вы используете буферизованный модуль записи, который не обязательно сразу сбрасывает свое содержимое в файл. Пока вы застряли в цикле, модуль записи ожидает дополнительной информации для записи, а остальную часть хранит в своем буфере. Вызов flush() может помочь вам с этой конкретной проблемой, но обеспечение достаточного количества покемонов для боя — более серьезная проблема.

person kdoomsday    schedule 16.02.2017
comment
Я только что обнаружил эту проблему, когда получил уведомление о том, что вы ответили. Я изначально не затронул этот вопрос. Спасибо за ваш отзыв! - person ; 16.02.2017
comment
Всегда рада помочь! - person kdoomsday; 16.02.2017