2014-03-25 50 views
0

我是一名初學java的學生,正在爲我的班級編寫一個gui tic-tac-toe程序。 (沒有玩家,只是計算機生成)。爲什麼循環不會停止迭代?

我的程序中的一切都按預期工作,除了一件事;似乎我的方法調用checkWinner的位置放置不正確,因爲X和O的分配總是完成。爲什麼這個循環不會在獲勝者結束後立即結束?

它會根據方法調用返回正確的獲勝者,但for循環將繼續迭代並填充其餘部分(所以有時它看起來像x和o勝或兩勝兩次)。我一直在瘋狂,認爲這可能是我的checkWinner方法調用和if語句的位置。當我設置winner = true;不應該取消循環?我試圖把它之間,內部和外部每個for-loop沒有運氣:(

我已標記的區域,我認爲是問題//這裏有什麼問題?//關閉在右邊分開的代碼。謝謝你的任何輸入!! :)

public void actionPerformed(ActionEvent e) 
    { 
    int total = 0, i = 0; 
    boolean winner = false; 


    //stop current game if a winner is found 
    do{ 

     // Generate random # 0-1 for the labels and assign 
     // X for a 0 value and O for a 1 value 

     for (int row = 0; row < gameboard.length; row++) //rows 
     { 
     for (int col = 0; col < gameboard[row].length; col++) //columns 
     { 

      //Generate random number 
      gameboard[row][col] = (int)(Math.random() * 2); 

      //Assign proper values 
      if(gameboard[row][col] == 0) 
      { 
      labels[i].setText("X"); 
      gameboard[row][col] = 10; //this will help check for the winner 
      } 

      else if(gameboard[row][col] == 1) 
      { 
      labels[i].setText("O"); 
      gameboard[row][col] = 100; //this will help check for winner 
      }    


      /**Send the array a the method to find a winner 
      The x's are counted as 10s 
      The 0s are counted as 100s 
      if any row, column or diag = 30, X wins 
      if any row, column or diag = 300, Y wins 
      else it will be a tie 
      */ 

      total = checkWinner(gameboard);  **//Is this okay here??//** 
      if(total == 30 || total == 300)  // 
      winner = true;    //Shouldn't this cancel the do-while? 


      i++; //next label 

     } 
     }//end for 
    }while(!winner);//end while 



    //DISPLAY WINNER 
    if(total == 30) 
     JOptionPane.showMessageDialog(null, "X is the Winner!"); 
    else if(total == 300) 
     JOptionPane.showMessageDialog(null, "0 is the Winner!"); 
    else 
     JOptionPane.showMessageDialog(null, "It was a tie!"); 
    } 
+2

checkWinner代碼? –

+1

Sidenode:如果找不到贏家,會發生什麼情況?遊戲將重新開始(不中止),所以你的「領帶」選項是不可能的。 – dognose

+0

當您將'winner'標誌設置爲'true'時,嘗試向System.out輸出消息;確保它確實發生。 –

回答

0

首先,你的代碼進行迭代,併產生X的隨機標記:要允許領帶,你不需要,而在所有的外部,並且可以馬上離開這兩個維權,當獲勝者發現和O.這導致了一些非常奇怪的棋盤狀態,總是逐行填充,並且可能具有不平衡的X和O標記。

恕我直言,你應該以相反的方式組織你的代碼,以填補董事會相似的真正的遊戲。我的意思是一系列9分的'XOXOXOXOX'在整個董事會中蔓延。

Labels labels爲9個字符的數組,初始化爲9個空格。

public int doGame(Labels labels) 
{ 
    labels = "   "; 
    int itisXmove = true;    // player X or O turn 
    for(int movesLeft = 9; movesLeft > 0; movesLeft --) 
    { 
     int position =   // 0 .. movesLeft-1 
       (int) Math.floor(Math.random() * movesLeft); 

     for(int pos = 0; pos < 9; pos ++)  // find position 
      if(labels[ pos] == " ")    // unused pos? 
       if(position-- == 0)    // countdown 
       { 
        if(itisXmove)    // use the pos 
         labels[ pos] = "X";  // for current player 
        else 
         labels[ pos] = "O"; 
        break; 
       } 

     int result = checkWinner(labels);  // who wins (non-zero)? 
     if(result != 0) 
      return result; 

     itisXmove = ! itisXmove;     // next turn 
    } 
    return 0;          // a tie 
} 

然後

public void actionPerformed(ActionEvent e) 
{ 
    Labels labels; 

    int result = doGame(labels); 

    if(result == valueForX) 
     JOptionPane.showMessageDialog(null, "X is the Winner!"); 
    else if(result == valueForO) 
     JOptionPane.showMessageDialog(null, "O is the Winner!"); 
    else 
     JOptionPane.showMessageDialog(null, "It's a tie!"); 

    for(int rowpos = 0; rowpos < 9; rowpos += 3) 
    { 
     for(int colpos = 0; colpos < 3; colpos ++) 
      /* output (char)label[ rowpos + colpos] */; 

     /* output (char)newline */; 
    } 
} 
+0

有些改進:玩家在3次移動之前不能獲勝,所以當'movesLeft'小於5時,我們可以有條件地調用'checkWinner'。另外我們不需要檢查整個棋盤 - 獲勝的三人必須在排,或在一個柱子或在當前移動完成的對角線。當然,贏家只能是當前行動的玩家。因此,'checkWinner'例程應該獲得'labels'和'pos'參數,從'labels [pos]'中獲取標籤,並根據pos值將其與2,3或4對其他位置進行比較。然後返回該標籤或零。 – CiaPan

0

你不檢查,直到兩個for循環完成的winner值。添加break設置winner = true之後,並添加

if (winner) 
{ 
    break; 
} 

你的外循環for的開頭或結尾。

+0

他正在檢查它的內部循環。只是輸出結束後。 – dognose

+1

@JasonC它肯定會阻止'for'循環在有贏家時終止。在'for'循環中'winner'的值將被設置爲'true',但'while'條件將不會被檢查直到兩個for循環完成。 –

+0

@dognose他在'for'循環內設置'winner'的值,但直到while循環完成迭代之後纔會檢查該值。正如所寫的,爲了讓'while'循環完成迭代,'for'循環都必須運行完成。 –

0

你的問題是,你的do/while語句是圍繞for陳述。所以for報表最終在達到while聲明之前運行整個週期。溶液來解決這個問題正在檢查在for聲明贏家和斷裂:

//stop current game if a winner is found 
do { 

    for (int row = 0; row < gameboard.length; row++) //rows 
    { 
     for (int col = 0; col < gameboard[row].length; col++) //columns 
     { 

      // ... your other code ... 

      total = checkWinner(gameboard); 
      if(total == 30 || total == 300) { 
       winner = true; 
       break; // end current for-loop 
      } 

      i++; //next label 
     } 

     if (winner) break; // we have a winner so we want to kill the for-loop 
    } //end for 

} while(!winner); //end while 

所以,你應該能夠僅僅通過兩個用於語句循環並在一個勝利者打破。你的代碼似乎也不能處理一個並列的情況,但我猜你已經知道了。

+0

@ dognose雖然這不是理想的行爲。操作者希望遊戲在獲勝者結束後立即結束,而不是在所有字段填滿之後結束。 –

+0

@MikeB,不,我只是在錯誤的地方有第二次休息聲明,所以它不會正常工作。 Dognose是對的,但我編輯了我的帖子。 – Firo

+0

1)您可以在'for'繼續條件中添加'!winner':for(int col = 0; col

0

我認爲你應該改變你的循環條件並添加一個更多的布爾。

你有一個「領帶」的條件,但目前你只檢查獲勝者。沒有checkWinner代碼的唯一解釋是你每次都遇到一條領帶。

所以......

boolean tie; 
boolean winner; 

do { 
//your stuff 
} 
while(!(tie || winner)) 

編輯:我不知道你把while循環外的for循環,你將需要爲了打破你的for循環爲while條件是檢查。

//stop current game if a winner is found 
    do{ 

     for (int row = 0; row < gameboard.length; row++) //rows 
     { 
     for (int col = 0; col < gameboard[row].length; col++) //columns 
     { 
      if(winner || tie) 
       break; 
     }//end for 

     if(winner || tie) 
      break; 
     }//end for 
    }while(!(winner || tie));//end while 
//the rest of your stuff here 
2

最簡單辦法是打破所有循環一次。 (即使有些人不喜歡這樣)

outerwhile: while(true){ 

    // Generate random # 0-1 for the labels and assign 
    // X for a 0 value and O for a 1 value 

    for (int row = 0; row < gameboard.length; row++) //rows 
    { 
    for (int col = 0; col < gameboard[row].length; col++) //columns 
    { 

     total = checkWinner(gameboard);  
     if(total == 30 || total == 300)   
     break outerwhile; //leave outer while, implicit canceling all inner fors. 


     i++; //next label 
    } 
    }//end for 
}//end while 

這可是不允許的「領帶」的選項,因爲雖然基本上都會重新開始遊戲,如果沒有贏家已經找到。通過板

Boolean winner = false; 
    outerfor: for (int row = 0; row < gameboard.length; row++) //rows 
    { 
    for (int col = 0; col < gameboard[row].length; col++) //columns 
    { 

     total = checkWinner(gameboard);  
     if(total == 30 || total == 300){   
     winner = true;  
     break outerfor; //leave outer for, implicit canceling inner for. 

     } 

     i++; //next label 
    } 
    }//end for 

    if (winner){ 
    //winner 
    }else{ 
    //tie. 
    } 
+0

如果您發現標籤+'break'令人不快,另一種方法是'while(!winner)'並將'&&!winner'添加到循環條件的內部。 –

+0

更好的辦法是首先考慮一下這段代碼是做什麼的,而不是所有這些都打破。原始代碼看起來像是更新標籤並更換遊戲板中的數字,這是一種不應影響「贏家」狀態的動作。循環和更新標籤會更有意義,以便不*執行0-> 10和1-> 100替換,並且只需在之後檢查一次獲勝者。 –

+0

我試過這兩個,但是我的輸出永遠不會通過前三個標籤。無論我按下新遊戲按鈕多少次。 – GessaGessa

相關問題