Search code examples
javaloopsdo-whiletic-tac-toe

Why won't the loop stop iterating?


I am a beginner java student writing a gui tic-tac-toe program for my class. (No players, just computer generated).

Everything in my program works as expected, except for one thing; it seems that the placement of my method call for checkWinner is not place correctly, because the assignment for the X's and O's always finish. Why won't the loop end as soon as there is a winner?

It will return the correct winner based on the method call, but the for-loop will continue to iterate and fill in the rest (so sometimes it looks like both the x and o win or one wins twice). I've been going crazy, thinking it might be the placement of my checkWinner method call and if statement. When I set the winner = true; shouldn't that cancel the loop? I have tried putting it between, inside and outside each for-loop with no luck :(

I have marked the area I think is the problem //What is wrong here?// off to the right of that part the code. Thank you for any input!! :)

  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!");
  }

Solution

  • First of all, your code iterates through a board and generates random marks of X and O. This leads to some very odd board states, being always filled row-by-row, and possibly with unbalanced number of X and O marks.

    IMHO you should organize your code in opposite manner to fill a board similary to a true game. I mean a series of 9 marks 'XOXOXOXOX' spreaded over the board.

    Let Labels labels be a nine-character array, initialized to 9 spaces.

    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
    }
    

    then

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