Можно ли кратко использовать сложное условие для цикла while?

Я работаю над игрой, в которой использую класс, который позволит пользователю вводить выбор в виде строки для одного из трех вариантов: «атака», «защита» или «бегство». Это может быть логически обработано с помощью «исключающего ИЛИ» (XOR). Я решил попробовать использовать цикл while, используя эту логику вместо обычной конструкции Switch, чтобы посмотреть, что произойдет, вооружившись лишь небольшим количеством дискретной математики. Я знал, что условие while будет уродливым и длинным, но оно работает, черт возьми!, и мне это нравится! Я хотел знать, так как я хотел бы повторно использовать этот цикл while в других разделах кода, если бы был какой-то способ сохранить условие цикла while (например, как переменную, метод или что-то еще), чтобы я мог поместить его в в то время как условие цикла и не занимать 8 строк кода каждый раз. Вот мой цикл while. Не смейтесь, это работает. И это позволяет избежать попытки поймать. На самом деле работает очень чисто. Я разместил метод, который я использую ниже. Этот метод вызывается другим классом:

public static void fighterAction(){  
    String selection = null;
    Scanner userChoice = new Scanner(System.in);

//Fighter 1 chooses combat action to perform: this is performed by 
//(XOR) logic:
//(( a  || b ) && !( a && b ) || c ) && !((( a || b ) && !( a && b ) && c ))

    while((( !"attack".equals(selection)  || !"defend".equals(selection) ) 
            && !( !"attack".equals(selection) && !"defend".equals(selection)
            ) || !"flee".equals(selection) ) &&
            !((( !"attack".equals(selection) || !"defend".equals(selection)
            ) && !( !"attack".equals(selection) && 
            !"defend".equals(selection) ) && !"flee".equals(selection) )))
    {    
        System.out.println("Choose action: attack  defend  flee\n\nEnter: ");
        selection = userChoice.next();
        if((( !"attack".equals(selection)  || !"defend".equals(selection) ) 
                && !( !"attack".equals(selection) && 
                !"defend".equals(selection) ) || !"flee".equals(selection) )
                && !((( !"attack".equals(selection) || 
                !"defend".equals(selection) ) && 
                !( !"attack".equals(selection) && 
                !"defend".equals(selection) ) && 
                !"flee".equals(selection) )))
        {
            System.out.println("Invalid Entry!");
        }else{
        System.out.println(selection + " was chosen");
        System.out.println("");
        }
    }        
}

Опять же, я спрашиваю, есть ли способ использовать это предложение while (которое, я подчеркиваю, работает отлично):

(( !"атака".равные(выборка) || !"защита".равные(выборка) ) && !( !"атака".равные(выборка) && !"защита".равные(выборка) ) || !" бежать".равно(выбор) ) && !((( !"атака".равно(выбор) || !"защитить".равно(выбор) ) && !( !"атака".равно(выбор) && !"защитить ".equals(выборка) ) && !"flee".equals(выборка)) ))

чтобы он соответствовал условию цикла while:

 while(FITS HERE){}  

Спасибо!


person Smith Will Suffice    schedule 15.10.2013    source источник


Ответы (3)


Он будет «подходить» как есть, другими словами, вы можете использовать его как есть, но его будет трудно читать и, что более важно, трудно отлаживать. Чтобы сделать его красивее, превратите его в метод.


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

public enum UserOption {
  ATTACK, DEFEND, FLEE
}

Метод, ожидающий этого перечисления, может принимать только одну из трех констант перечисления (или null), что дает вам проверку типов во время компиляции и ограничение пользовательских параметров, а также приводит к более красивому, более повторно используемому и расширяемому коду.

Тогда ваше консольное приложение может иметь метод проверки:

public boolean validateUserOptionsString(String text) {
  for (UserOption option : UserOption.Values() {
    if (text.equalsIgnoreCase(option.toString())) {
      return true;
    }
  }
  return false;
}
person Hovercraft Full Of Eels    schedule 15.10.2013
comment
Кроме того, вы можете повторно использовать этот метод для улучшения оператора if... ! - person user268396; 16.10.2013

Воу, воу, воу. selection может иметь только одно значение за раз. Существует ряд рефакторингов, которые могли бы сделать этот код намного чище (например, использование перечисления, а не внедрение магических констант), но вы можете логически свернуть все это в

while(!"attack".equals(selection) && !"defend".equals(selection) && !"flee".equals(selection)) { ... }
person chrylis -cautiouslyoptimistic-    schedule 15.10.2013

Вот так бы я написал

String select;
while (true) {
   System.out.println("Enter: attack, defend or flee");
   selection = userChoice.nextLine();
   if (select.equals("attack") || select.equals("defend")||select.equals("flee"))
       break;
   System.out.println("Invalid input: " + select);
}
person Peter Lawrey    schedule 15.10.2013