2014-11-21 33 views
1

當遊戲執行時,玩家可以進入一個移動,但然後它卡在一個循環中,邏輯錯誤是在isWinner方法,但我不知道該怎麼做沒有使用一堆長長的if語句?請幫助我不能發現我的邏輯錯誤

public class TicTacToe { 

    public static char board[] = new char[10]; 

    public static void resetgame(){ 
     for (int x = 0; x < board.length; x++) 
      board[x] = '-'; // resets board to all - 
    } 

    public static void displayBoard(){ 
     for (int x = 1; x < board.length; x++){ 
      if (board[x] == '-') 
       System.out.print(x + " "); 
      else 
       System.out.print(board[x] + " "); 
      if (x % 3 == 0) 
       System.out.println(); 
     } 
    } 

    public static boolean isSpotEmpty(int m){ 
     return (board[m] == '-');   
    } 

    public static void getPlayerMove(){ 
     Scanner input = new Scanner(System.in); 
     System.out.print("Enter your move (1-9): "); 
     int move = input.nextInt(); 
     while (move < 1 || move > 9 || !isSpotEmpty(move)){ //validate move 
      System.out.print("Move is not valid. Reenter move (1-9): "); 
      move = input.nextInt(); 
     } 
     board[move] = 'X'; 
    } 

    public static void computerMove(){ 
     int move = ((int)(Math.random() * 9)+1);    
     while (isSpotEmpty(move)==false) 
      move = ((int)(Math.random() * 9)+1); 
     board[move] = 'O';   
    } 

    public static boolean isWinner(char ch){ 

     for(int x = 1; x < 4; x++){ 
      while (board[x] != ch) 
       return false;} 
     for(int x = 4; x < 7; x++){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 7; x < board.length; x++){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 1; x < 8; x += 3){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 2; x < 9; x += 3){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 3; x < board.length; x += 3){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 1; x < board.length; x += 4){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 3; x < 8; x += 2){ 
      while (board[x] != ch) 
       return false;} 
     return true; 
    } 

    public static boolean isFull(){ 
     boolean draw = false; 
     for (int x = 0; x < board.length; x++){ 
      while (board[x] != '-') 
       draw = true; 
     } 
     return draw; 
    } 

    public static boolean isGameDone(){ 
     if (isWinner('X')){ 
      System.out.println("Player wins!"); 
      return true; 
     } 
     if (isWinner('O')){ 
      System.out.println("You suck! Computer wins!"); 
      return true; 
     } 
     if (isFull()){ 
      System.out.println("Draw!"); 
      return true; 
     } 
     return false;   
    } 

    public static void tictactoe(){ 
     resetgame(); 
     displayBoard(); 
     while (true){ 
      getPlayerMove();   
      displayBoard(); 
      if (isGameDone()==true) return;   
      System.out.println("Computer's move!");      
      computerMove();      
      displayBoard(); 
      if (isGameDone()==true) return; 
      System.out.println("Your move!"); 
     } 
    } 

    public static void main(String[] args) { 

     tictactoe();  
    } 
} 
+0

您可以使用'switch'語句。 – 2014-11-21 05:19:26

+0

用'if'替換所有'while',看看它是否解決了這個問題。 – 2014-11-21 05:21:21

+0

嘗試過......沒有骰子 – Luke 2014-11-21 05:22:36

回答

0

您需要重構既isWinner()isFull()方法。你被困在一個無限循環中,因爲你在檢查第一個水平行後立即返回。如果這是錯誤的,其他循環都不會執行。

我還沒有做完整的代碼審查,但上面提到的bug可以通過下面的代碼修復。

boolean finishedFlag = true; 
for(int x = 1; x < 4; x++){ 
    if (board[x] != ch){ 
     finishedFlag = false; 
     break; 
    } 
} 
if(finishedFlag) return finishedFlag; 

/* 

... 
Check similarly for all horizontal,vertical and diagonal 
... 

*/ 

return finishedFlag; 

這個想法是在評估所有可能性而不是在每個循環中返回函數一次。 下面的條件有利於在任何成功的結果的情況下立即返回:

if(finishedFlag) return finishedFlag; 
+0

好吧,這是有道理的。謝謝你這麼好解釋。我按照你解釋的方式對它進行了重構,現在程序運行良好,只是不能確定贏家,或者如果板子滿了,它只是讓我玩,直到板子滿了並卡住,即使有贏家 – Luke 2014-11-21 05:55:53

+0

@Luke很高興知道它的工作。請不要停止我的建議,並嘗試進一步重構,以便您可以使其更具可讀性和簡潔性。我發現了這個錯誤,並給出了一個快速的解決方法,如果你給予更多的思考,這個代碼可以顯着提高。 – toddlermenot 2014-11-21 06:01:10

+0

所以我需要條件if(finishedFlag)return finishedFlag;每個循環之後? – Luke 2014-11-21 06:01:45

0

更新的代碼: 下面的代碼進行測試和工作。

isWinner方法

public static boolean isWinner(char ch){ 
    boolean finishFlag = true; 
    for(int x = 1; x < 4; x++){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for(int x = 4; x < 7; x++){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 7; x < board.length; x++){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 1; x < 8; x += 3){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 2; x < 9; x += 3){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 3; x < board.length; x += 3){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 1; x < board.length; x += 4){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 3; x < 8; x += 2){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    return finishFlag; 
} 

isFull方法

public static boolean isFull(){ 
    boolean draw = false; 
    for (int x = 1; x < board.length; x++){ 
     if (board[x] == '-') { 
      draw = false; 
      break; 
     } else { 
      draw = true; 
     } 
    } 
    return draw; 
} 

編輯:在isFull初始化x到1,而不是0()

+0

結果是相同的,無限循環。我打算做一個for循環來檢查棋盤上的每一行,每列和對角線上是否有3 X或O的組合......它不像我做的那樣 – Luke 2014-11-21 05:28:10

+0

Luke,你需要重構isWinner(),該功能正在走很長的路。 – 2014-11-21 05:29:20

+0

我應該如何重構它? – Luke 2014-11-21 05:31:54

0

我會有點鈍這裏。您的問題是由於濫用了while運營商。讓我們來看看其中的問題:

while (board[x] != '-') 
    draw = true; 

當我們在循環,我們要問:

  1. 是我的條件真的在循環的開始?
  2. 循環過程中會發生什麼變化?
  3. 我的條件在循環結束時是否真實?

條件是board[x] != '-'。在循環開始時,board[x]必須不等於'-'

while循環結束時,'-'當然不會改變,因爲它是一個常量字符串。

請問board[x]已經改變了嗎?我們來看看while循環的主體。唯一要做的是將true分配到drawx不會改變,board[x]也不會改變。

那麼,這個while循環會循環多久?看看您使用while的其他代碼,並瞭解它們的運行方式。

+0

謝謝你的幫助。我把他們全部改爲if。儘管如此,我會盡力記住那3個未來的問題 – Luke 2014-11-21 06:19:36