2012-05-04 41 views
1

首先,這是額外的信用功課的一部分,所以請不要給我答案。請幫我理解我可能遇到的問題。它是一個Tic-Tac-Toe發生器,遊戲通過遞歸確定基於玩家的最佳移動。 (教授使用白色「W」和黑色「B」代替X和O)爲什麼我的遞歸不會返回,而是以堆棧溢出結束?

我的主遞歸方法返回基於TTT板上輸入位置的狀態評分; 1,如果白色將迫使一個雙贏從該位置,0,如果它是一個平局,和-1,如果黑將迫使一個雙贏從該位置:

public int stateScore(boolean whiteMove, int[] BestMove) { 
    return stateScore(whiteMove,BestMove,TTTBoard); 
} 

這就要求我的下層專用遞歸方法:

private int stateScore(boolean whiteMove, int[] BestMove,char[][] TestBoard) { 
    char [][] newTestBoard = new char [3][3]; 
    for(int rowVal = 0; rowVal < 3; rowVal++){ 
     for(int colVal = 0; colVal < 3; colVal++){ 
      newTestBoard[rowVal][colVal] = TestBoard[rowVal][colVal]; 
     } 
    } 

    int [] bestMove = new int [2]; 

    for(int rowVal = 0; rowVal < 3; rowVal++){ 
     for(int colVal = 0; colVal < 3; colVal++){ 
      if(isFull(newTestBoard) == true){ 
       return 0; 
      } 
      else if(newTestBoard[rowVal][colVal] == '-'){ 
       bestMove[0] = rowVal; 
       bestMove[1] = colVal; 

       //if boolean is white 
       if(whiteMove == true){ 
        newTestBoard = testEntry(rowVal,colVal,'W',newTestBoard); 
        if(threeInRow(newTestBoard) == 1){ 
         return 1; 
        } 
        else if(threeInRow(newTestBoard) == 0 && isFull(newTestBoard) == true){ 
         return 0; 
        } 
        else if(threeInRow(newTestBoard) == -1 && isFull(newTestBoard) == true){ 
         return -1; 
        } 
        else{ 
         return stateScore(!whiteMove,bestMove,newTestBoard); 
        } 
       } 
       //if boolean is black 
       else{ 
        newTestBoard = testEntry(rowVal,colVal,'B',newTestBoard); 
        if(threeInRow(newTestBoard) == -1){ 
         return -1; 
        } 
        else if(threeInRow(newTestBoard) == 0 && isFull(newTestBoard) == true){ 
         return 0; 
        } 
        else if(threeInRow(newTestBoard) == 1 && isFull(newTestBoard) == true){ 
         return 1; 
        } 
        else{ 
         return stateScore(!whiteMove,bestMove); 
        } 
       } 
      } 
     } 
    } 
    return 0; 
} 

whiteMove的布爾值如果是白色的移動則爲true;如果是black的則爲false。函數內的二級方法包括threeInRow:

public int threeInRow(char[][] TTTBoard){ 
    boolean whiteIs = false; 
    boolean blackIs = false; 
     //Horizontal? 
     char [] colChar = new char [3]; 
     for(int rowVal = 0; rowVal < 3; rowVal ++){ 
      for(int colVal = 0; colVal < 3; colVal++){ 
       colChar[colVal] = TTTBoard[rowVal][colVal]; 
      } 
      if(colChar[0] == colChar[1] && colChar[1] == colChar[2]){ 
       if(colChar[0] == 'W'){ 
        whiteIs = true; 
       } 
       if(colChar[0] == 'B'){ 
        blackIs = true; 
       } 
      } 
     } 

     //Vertical? 
     char [] rowChar = new char [3]; 
     for(int colVal = 0; colVal < 3; colVal ++){ 
      for(int rowVal = 0; rowVal < 3; rowVal++){ 
       rowChar[colVal] = TTTBoard[rowVal][colVal]; 
      } 
      if(rowChar[0] == rowChar[1] && rowChar[1] == rowChar[2]){ 
       if(rowChar[0] == 'W'){ 
        whiteIs = true; 
       } 
       else if(rowChar[0] == 'B'){ 
        blackIs = true; 
       } 
      } 
     } 

     //Diagonal 
      //topLeft to bottomRight 
      if(TTTBoard[0][0] == TTTBoard[1][1] && TTTBoard[1][1] == TTTBoard[2][2]){ 
       if(TTTBoard[0][0] == 'W'){ 
        whiteIs = true; 
       } 
       else if(TTTBoard[0][0] == 'B'){ 
        blackIs = true; 
       } 
      } 

      //topRight to bottomLeft 
      if(TTTBoard[0][2] == TTTBoard[1][1] && TTTBoard[1][1] == TTTBoard [2][0]){ 
       if(TTTBoard[1][1] == 'W'){ 
        whiteIs = true; 
       } 
       else if(TTTBoard[1][1] == 'B'){ 
        blackIs = true; 
       } 
      } 


    //Return Vals 
    if(whiteIs == true && blackIs == true){ 
     return 0; 
    } 
    else if(blackIs == true && whiteIs == false){ 
     return -1; 
    } 
    else if(blackIs == false && whiteIs == true){ 
     return 1; 
    } 
    else if(blackIs == false && whiteIs == false){ 
     return 0; 
    } 
    else{ 
     return 0; 
    } 

} 

和的TestEntry:

public char[][] testEntry(int row,int col,char newChar, char[][] TestBoard){ 

    char [][] returnBoard = new char[3][3]; 
    for(int rowVal = 0; rowVal < 3; rowVal++){ 
     for(int colVal = 0; colVal < 3; colVal++){ 
      returnBoard[rowVal][colVal] = TestBoard[rowVal][colVal]; 
     } 
    } 
    returnBoard[row][col] = newChar; 
    return returnBoard; 

} 

我不明白的地方堆棧溢出的來源。看起來我的回報似乎涵蓋了所有的情況,而且我的方法有合適的回報。我從來沒有用過遞歸循環,我是在搞這個。另外,我正確地說type [] name = name(同類型)不起作用,對吧?這就是爲什麼我在那種情況下做了for循環的原因。

+0

這是一個很大的代碼,請把它最小化一個最小的可編輯捕捉,仍然涵蓋了手頭的問題。 – amit

+0

抱歉無法抗拒:一場奇怪的比賽。唯一獲勝的舉動是不玩。如何一個不錯的國際象棋遊戲? – flolo

+0

我在這裏第二個馬可,扎克 - 你會花幾分鐘時間回顧你以前的六個問題嗎?他們都有答案(儘管如果你認爲沒有答案有幫助,在特定情況下不給予接受是沒問題的)。 – halfer

回答

4

在你的黑色分支你的回報是錯誤的。

您返回

return stateScore(!whiteMove,bestMove); 

其重新啓動遞歸。要返回

return stateScore(!whiteMove,bestMove,newTestBoard); 

提示:

  • 解決您的布爾值:

    if(whiteMove == true) -> if (whiteMove) 
    
  • 使用大寫的類,lowerCamelCase變量。

  • 如果你返回一個if分支,那麼你不需要別的。

    相反的:

    if (condition) { 
        ... 
        return ...; 
    } 
    else 
    { 
        ... 
    } 
    

    這是更好地寫:

    if (condition) { 
        ... 
        return ...; 
    } 
    ... 
    

    保持築巢,並且使得代碼更易於理解。

  • 重構公共代碼:兩個分支返回相同的結果:

    return stateScore(!whiteMove,bestMove,newTestBoard); 
    

    爲什麼不動這個之外,如果(whiteMove)

+0

非常感謝,包括提示。 –

+0

你去過哪裏? –

0

發佈堆棧跟蹤,但我敢打賭,這是當您遞歸調用stateScore時,您正在獲得無限遞歸。