2017-05-24 190 views
0

我是新來的Java和我的函數有很多try/catch塊,我想清理。我想把每個部分都放在一個單獨的輔助方法中,並且只在主函數中調用一些函數,但是當我這樣做時,我得到一個用於Scanner的java.util.NoSuchElementException。Java嘗試/捕捉方法

這是原始功能。任何幫助將非常感激。

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

你的問題是什麼? – luk2302

+2

顯示你修改後的代碼和導致'NoSuchElementException'的堆棧跟蹤 – SomeDude

+0

我不明白你爲什麼在這些情況下使用異常處理。例如,爲什麼在'default'塊中拋出'IllegalArgumentException'?爲什麼不直接在「catch」塊中直接運行代碼? – EJoshuaS

回答

3

首先,爲了不要讓java.util.NoSuchElementException,你需要檢查,如果下一行使用hasNextLine()存在。 加入,登記入住的while循環:

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

其次,你在其他意見得到了相當不錯的代碼風格技巧在這裏,我建議你把他們:)

0

幾點意見:

首先,您可以用簡單的if語句替換很多這些try/catch塊(或完全消除它們)。

例如:

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; 
    } 
    } 

爲什麼不只是做:

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; 

或類似的東西來代替?爲什麼要打擾例外?

而且,這種邏輯是不正確:

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

,它是一個整數,並不能證明它是有效卡的事實。如果有人輸入5,321,該怎麼辦?顯然,int,但它不是真正的卡。此外,請參閱here(及其重複)以瞭解封裝的方法。

+0

在做你的建議,有一個「未處理的IOException」,然後建議添加try/catch方法 – salivad