Search code examples
javaarraystic-tac-toe

TicTacToe resizable board, WIN method error


Hi just attempted a TicTacToe project and was stuck about an error. My error has to do with checking for win solutions specifically diagonals.

What I need: Create nested loop to loop down the array diagonally, then incrementing it so it would scan diagonally under or to the size until eventually scanning the entire array.

What I did: I tried to make a nested for loop that would loop through the rows and add the to the counter until the end of the row then check if the counter was equal to the inline (amount in a row needed to win). I believe it works for the rows and columns.

Problem: But for diagonals, I get an array out of bounds exception and I think it's because my a or b is added to i which could be gameBoard[3][4] when speaking of a 3x3 game board.

Attempt to solve: I attempted a solution which you can see is the oddly placed for loop with j. So that i would only go to j and not go past the array limits.

I'm wondering if the logic behind this would work?

Sorry if the code is messy especially with the added for loops contain j

/*
 * Method winner will determine if the symbol (X or O) wins
 *
 * @param symbol will be either X or O
 * @return will return true if the symbol has won from any of the methods
 */
public boolean winner(char symbol) {

  int counter = 0;

  /* Scan from ROWS for any symbols inline to win */

  for (int i = 0; i < gameBoard.length; i++) { // loop through the rows
    for (int j = 0; j < gameBoard.length; j++) { // Loop through the columns
      if (gameBoard[i][j] == symbol) {
        counter++;
      }
      if (gameBoard[i][j] != symbol) { // If the next one in the row is not equal then reset counter to 0
        counter = 0;
      }
      if (counter == inline) { // Counter will only equal inline if there is amount of inliine in a row
        return true;
      }
    }
  }

  /* Scan and search for winning conditions in COLUMNS */
  for (int i = 0; i < gameBoard.length; i++) { // loop through the rows
    for (int j = 0; j < gameBoard.length; j++) { // Loop through the columns
      if (gameBoard[j][i] == symbol) {
        counter++;
      }
      if (gameBoard[j][i] != symbol) { // Reset counter to 0 if not equal to symbol 
        counter = 0;
      }
      if (counter == inline) { // If counter reached amount of inline then it must have had amount of inline in a row to win
        return true;
      }
    }
  }

  /* Scan for RIGHT DIAGONALS for winning conditions */

  // a shifts the position of diagonal to the right by one
  // after diagonally looping through the board
  for (int a = 0; a < gameBoard.length; a++) {

    // i loops diagonally through the board
    for (int j = gameBoard.length; j < 0; j--) {
      for (int i = 0; i < j; i++) {
        if (gameBoard[i][i + a] == symbol) {
          counter++;
        }
        if (gameBoard[i][i + a] != symbol) {
          counter = 0;
        }
        if (counter == inline) {
          return true;
        }
      }
    }
  }

  // b shifts the position of the diagonal down by one
  for (int b = 1; b < gameBoard.length; b++) {

    for (int j = gameBoard.length - 1; j < 0; j--)
    // i loops diagonally through the board
      for (int i = 0; i < j; i++) {
      if (gameBoard[i + b][i] == symbol) {
        counter++;
      }
      if (gameBoard[i + b][i] != symbol) {
        counter = 0;
      }
      if (counter == inline) {
        return true;
      }
    }
  }

  /* Scan for LEFT DIAGONALS for winning conditions */

  // a shifts the position of diagonal to the left by one
  for (int a = gameBoard.length; a >= 0; a--) {
    for (int j = gameBoard.length; j < 0; j--) {
      // i loops diagonally through the board
      for (int i = 0; i < j; i++) {
        if (gameBoard[i][a - i] == symbol) {
          counter++;
        }
        if (gameBoard[i][a - i] != symbol) {
          counter = 0;
        }
        if (counter == inline) {
          return true;
        }
      }
    }
  }

  // b shifts the position of the diagonal down by one
  for (int b = 0; b < gameBoard.length; b++) {
    for (int j = gameBoard.length - 1; j < 0; j--) {
      // i loops diagonally in the left direction of through the board
      for (int i = 0; i < j; i++) {
        if (gameBoard[i + b][gameBoard.length - i] == symbol) {
          counter++;
        }
        if (gameBoard[i + b][gameBoard.length - i] != symbol) {
          counter = 0;
        }
        if (counter == inline) {
          return true;
        }
      }
    }
  }


  return false; // If it reaches here then no one has won yet and the game is ongoing

}

Solution

  • As far as i see in your code you must get Array Index Out Of Bounds Exception. I assume you try to implement classic tic-tac-toe, so we are dealing with 3x3 matrix. Here is how your game board is indexed:

    [0.0] [1.0] [2.0]

    [0.1] [1.1] [2.1]

    [0.2] [1.2] [2.2]

    So this is what happens in your loop with Right Diagonals:
    int a increments 0 --> 2
    int j decrements 2 --> 0
    int i increments 0 --> 2


    So your loop goes like this:
    [0.0+0] --> i++ [1.1+0] --> i++ [2.2+0] j--
    [0.0+0] --> i++ [1.1+0] j--
    [0.0+0] a++
    [0.0+1] --> i++ [1.1+1] --> i++ [2.2+1] j-- <--Here you get out of Array.


    Additionally after checking through main diagonal, you go through [0.0] [1.1] which is not diagonal at all and you already did this in loops for rows. Even shifting through bottom diagonal is not needed ([0.1][1.2]) as you already did this in loops before. So checking through [0.0] [1.1] [2.2] will do work for you.


    I believe that this is ineffective way to check for win condition. You can get rid of 3 loops, just by storing position of found element.