2014-03-25 47 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

相关问题