2017-05-24 4 views
0

Ich bin neu in Java und meine Funktion hat viele Versuch/catch-Blöcke, die ich aufräumen möchte. Ich wollte jeden Abschnitt nehmen und in eine separate private Hilfsmethode einfügen und nur ein paar Funktionen innerhalb der Hauptfunktion aufrufen, aber wenn ich dies tue, erhalte ich eine java.util.NoSuchElementException für den Scanner.Java try/catch Methode

Hier ist die ursprüngliche Funktion. Jede Hilfe würde sehr geschätzt werden.

public void playGame(List<Card> deck, FreecellOperations<Card> model, int numCascades, 
        int numOpens, boolean shuffle) { 
try { 
    Scanner scan = new Scanner(rd); 

try { 
    Objects.requireNonNull(model); 
    Objects.requireNonNull(deck); 
} catch (NullPointerException npe) { 
    throw new IllegalArgumentException("Cannot start game with null parameters."); 
} 

try { 
    model.startGame(deck, numCascades, numOpens, shuffle); 
} catch (IllegalArgumentException iae) { 
    ap.append("Could not start game. " + iae.getMessage()); 
    return; 
} 

    ap.append(model.getGameState() + "\n"); 
    while (!model.isGameOver()) { 
    String source = scan.next(); 
    if (source.substring(0, 1).equals("q") || source.substring(0, 1).equals("Q")) { 
     ap.append("Game quit prematurely."); 
     return; 
    } 
    String cardIndex = scan.next(); 
    if (cardIndex.substring(0, 1).equals("q") || cardIndex.substring(0, 1).equals("Q")) { 
     ap.append("Game quit prematurely."); 
     return; 
    } 
    String destination = scan.next(); 
    if (destination.substring(0, 1).equals("q") || destination.substring(0, 1).equals("Q")) { 
     ap.append("Game quit prematurely."); 
     return; 
    } 

    int pileNumber = 0; 
    PileType sourceType = null; 
    boolean isValidSource = false; 
    while (!isValidSource) { 
     try { 
     switch (source.charAt(0)) { 
      case 'F': 
      sourceType = PileType.FOUNDATION; 
      pileNumber = this.validMoveCheck(source, 4); 
      isValidSource = true; 
      break; 
      case 'O': 
      sourceType = PileType.OPEN; 
      pileNumber = this.validMoveCheck(source, numOpens); 
      isValidSource = true; 
      break; 
      case 'C': 
      sourceType = PileType.CASCADE; 
      pileNumber = this.validMoveCheck(source, numCascades); 
      isValidSource = true; 
      break; 
      default: 
      throw new IllegalArgumentException(); 
     } 
     } catch (IllegalArgumentException iae) { 
     ap.append("Invalid source pile. Try again.\n"); 
     source = scan.next(); 
     if (source.equals("q") || source.equals("Q")) { 
      ap.append("Game quit prematurely."); 
      return; 
     } 
     } 
    } 
    int cardNum = 0; 
    boolean isValidCard = false; 
    while (!isValidCard) { 
     try { 
     cardNum = Integer.parseInt(cardIndex); 
     isValidCard = true; 
     } catch (NumberFormatException nfe) { 
     ap.append("Invalid card number. Try again.\n"); 
     cardIndex = scan.next(); 
     if (cardIndex.equals("Q") || cardIndex.equals("q")) { 
      ap.append("Game quit prematurely."); 
      return; 
     } 
     } 
    } 

    PileType destType = null; 
    int destPileNum = 0; 
    boolean isValidDest = false; 
    while (!isValidDest) { 
     try { 
     switch (destination.charAt(0)) { 
      case 'F': 
      destType = PileType.FOUNDATION; 
      destPileNum = this.validMoveCheck(destination, 4); 
      isValidDest = true; 
      break; 
      case 'C': 
      destType = PileType.CASCADE; 
      destPileNum = this.validMoveCheck(destination, numCascades); 
      isValidDest = true; 
      break; 
      case 'O': 
      destType = PileType.OPEN; 
      destPileNum = this.validMoveCheck(destination, 4); 
      isValidDest = true; 
      break; 
      default: 
      throw new IllegalArgumentException(); 
     } 
     } catch (IllegalArgumentException iae) { 
     ap.append("Invalid destination pile. Try again.\n"); 
     destination = scan.next(); 
     if (destination.equals("q") || destination.equals("Q")) { 
      ap.append("Game quit prematurely."); 
      return; 
     } 
     } 
    } 
    try { 
     model.move(sourceType, (pileNumber - 1), (cardNum - 1), destType, (destPileNum - 1)); 
     ap.append(model.getGameState() + "\n"); 
    } catch (IllegalArgumentException iae) { 
     ap.append("Invalid move. Try again. " + iae.getMessage() + "\n"); 
    } 
    } 
    ap.append("Game over."); 
} catch (IOException ioe) { 
    return; 
} 
} 
+0

Und was ist Ihre Frage? – luk2302

+2

Zeigen Sie Ihren modifizierten Code und den Stack-Trace, der zu 'NoSuchElementException' führt – SomeDude

+0

Ich verstehe nicht, warum Sie in diesen Fällen die Ausnahmebehandlung verwenden. Warum zum Beispiel eine 'IllegalArgumentException' im' default' Block werfen? Warum nicht einfach den Code in diesem "Fang" -Block "direkt" ausführen? – EJoshuaS

Antwort

3

Zuerst Um java.util.NoSuchElementException nicht zu bekommen, müssen Sie überprüfen, ob die nächste ZeilehasNextLine() Verwendung existiert. dass der Check-in Ihre while-Schleife hinzufügen:

while (!model.isGameOver() && scan.hasNextLine()) { 
... 
} 

Zweitens Sie hier ziemlich gut Code Styling-Tipps in den anderen Kommentare bekommen, empfehle ich Ihnen, sie zu nehmen :)

0

Einige Kommentare:

Zuerst können Sie viele dieser try/catch-Blöcke durch einfache if-Anweisungen ersetzen (oder sie ganz eliminieren).

Zum Beispiel:

default: 
     throw new IllegalArgumentException(); 
    } 
    } catch (IllegalArgumentException iae) { 
    ap.append("Invalid destination pile. Try again.\n"); 
    destination = scan.next(); 
    if (destination.equals("q") || destination.equals("Q")) { 
     ap.append("Game quit prematurely."); 
     return; 
    } 
    } 

Warum nicht einfach tun:

default: 
    ap.append("Invalid destination pile. Try again.\n"); 
    destination = scan.next(); 
    if (destination.equals("q") || destination.equals("Q")) { 
     ap.append("Game quit prematurely."); 
     return; 
    } 
    break; 

oder so ähnlich statt? Warum sollte man sich mit der Ausnahme befassen?

Auch diese Logik ist falsch:

cardNum = Integer.parseInt(cardIndex); 
isValidCard = true; 

Die Tatsache, dass es eine ganze Zahl ist, beweist nicht, dass es eine gültige Karte ist. Was ist, wenn jemand 5.321 eingegeben hat? Natürlich ist das ein int, aber es ist keine echte Karte. Siehe auch here (sowie seine Duplikate) für Möglichkeiten, dies zu kapseln.

+0

Wenn Sie das tun, was Sie vorgeschlagen haben, gibt es eine "Unhandled IOException", die dann vorschlägt, eine try/catch-Methode hinzuzufügen – salivad