简体   繁体   中英

How to fix stackOverFlow error

The program works fine at first, but after the sixth turn, it returns a stackOverFlow error. I cannot make the program work unless the play method calls itself until either the user or the computer wins. How can I fix this problem?

TicTacToeTester

public class TicTacToeTester {

public static void main(String[] args)
{

String name = JOptionPane.showInputDialog("Welcome to the Tic-Tac-Toe game! What is your name?");
JOptionPane.showMessageDialog(null, "Nice to meet you, " + name + ", we'll now decide whose turn it is");

//decide who will go first
Random r = new Random();  
int x = r.nextInt(2);
String turn = " ";
char mark = ' ';

if (x == 0)
{
  JOptionPane.showMessageDialog(null, "The computer will go first");
  turn = "Computer";
  mark = 'O';
}
else
{
  JOptionPane.showMessageDialog(null, "Congrats! You will go first");
  turn = "Player";
  mark = 'X';
}

//create game
TicTacToe game = new TicTacToe(name, turn);
game.play(turn, mark);

}
}

TicTacToe

public class TicTacToe {

private String name;
private char[][] board = new char[3][3]; 
Random r = new Random(); 
private static char mark;
private static String turn;

//constructor 
public TicTacToe(String name, String turn)
{
   this.name = name;
   this.turn = turn;
   initializeBoard();
}


public void initializeBoard() {  

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            board[i][j] = '-';
        }
    }
}

public void printBoard()
{
  JOptionPane.showMessageDialog(null, board[0][0] + "|" + board[0][1] + "|" +  board[0][2] + "\n"   
                                  + board[1][0] + "|" + board[1][1] + "|" + board[1][2] + "\n"
                                  + board[2][0] + "|" + board[2][1] + "|" + board[2][2] );  
}

public boolean isFull()
{
 boolean isFull = true;

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i][j] == '-') {
                isFull = false;
            }
        }
    }
    return isFull;
}

 public boolean isEmpty(int row, int col)
 {
   if ((row >= 0 && row < 3) &&
     (col >= 0 && col < 3) &&
      (board[row][col] == '-'))
   return true;
   else
   return false;
 }

public void play(String turn, char mark)
{

 if (turn.equals("Player") && !checkForWinner() && !isFull())
 {
    mark = 'X';
   JOptionPane.showMessageDialog(null, "Think about where you would like to place your mark");
   int row = Integer.parseInt (JOptionPane.showInputDialog("Type row")) - 1;
   int col = Integer.parseInt (JOptionPane.showInputDialog("Type column")) - 1;

   if (isEmpty(row,col) == true)
   {
        board[row][col] = mark;
        printBoard();

        if (checkForWinner() == true)
          JOptionPane.showMessageDialog(null, "Congrats, you won!");
        else if (isFull() == true)
          JOptionPane.showMessageDialog(null, "We have a tie!");
        else
        {
         JOptionPane.showMessageDialog(null, "It's the computer's turn");
         play("Computer", 'O');
        }
       }

   else 
   {
     JOptionPane.showMessageDialog(null, "That slot is already occupied or it does not exist. Please show a new one");
     play("Player", 'X');
  }
}

 else if (turn.equals("Computer") && !checkForWinner() && !isFull())
 {
   mark = 'O';

   int col = r.nextInt(2);
   int row = r.nextInt(2);

       if (isEmpty(row,col) == true)
      {
        board[row][col] = mark;
        printBoard();

        if (checkForWinner() == true)
          JOptionPane.showMessageDialog(null, "Sorry, the computer won!");
        else if (isFull() == true)
          JOptionPane.showMessageDialog(null, "We have a tie!");
        else
        {
         JOptionPane.showMessageDialog(null, "It's your turn");
         play("Player", 'X');
        }
      }

      else 
        play("Computer", 'X');
    }
  }   


public boolean checkForWinner()
{
  return (checkRows() || checkCols() || checkDiagonals());
}

private boolean checkRows() {
    for (int i = 0; i < 3; i++) {
        if (checkRowCol(board[i][0], board[i][1], board[i][2]) == true) {
            return true;
        }
    }
    return false;
 }


private boolean checkCols() {
    for (int i = 0; i < 3; i++) {
        if (checkRowCol(board[0][i], board[1][i], board[2][i]) == true) {
            return true;
        }
    }
    return false;
}


private boolean checkDiagonals() {
    return ((checkRowCol(board[0][0], board[1][1], board[2][2]) == true) || (checkRowCol(board[0][2], board[1][1], board[2][0]) == true));
}

// Check to see if all three values are the same (and not empty) indicating a win.
private boolean checkRowCol(char c1, char c2, char c3) {
    return ((c1 != '-') && (c1 == c2) && (c2 == c3));
}

}

I cannot make the program work unless the play method calls itself until either the user or the computer wins.

I would dispute that. ANY program that uses recursion can be transformed into an equivalent one that uses loops.

How can I fix this problem?

In general, there are two approaches.

  • Rewrite the program to use loops instead of recursion. This is (IMO) the better solution.

  • Use a bigger stack. For example java -Xss 10m ... will run your application with a 10Mbyte stack.

However, the problem could be caused by a bug that is causing infinite recursion. If that is the case, then a bigger stack won't help.

In fact, I suspect that that is probably the case here, because a game of tic-tac-toe should only recurse to a depth of 9 before the entire board is filled ... and the game ends. 9 levels of recursion should be fine for the default Java stack size.

So, if you want to stick with a recursive algorithm, then you need to carefully analyze the recursion patterns and termination conditions for the algorithm, and check that you have implemented them correctly. (There is rather too much code to expect one of us to do that work for you ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM