OutOfBoundsException для игры TicTacToe; Выпуск: массивы? - PullRequest
0 голосов
/ 28 октября 2010

Я начинаю писать игру в крестики-нолики.Я просто запустил его и получил следующую трассировку стека:

 Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
 at java.util.ArrayList.rangeCheck(ArrayList.java:571)
 at java.util.ArrayList.get(ArrayList.java:349)
 at TicTacToe.isMarked(TicTacToe.java:23)
 at TicTacToe.mark(TicTacToe.java:59)
 at TicTacToe.main(TicTacToe.java:7)

Я подозреваю, что это проблема с тем, как я установил ArrayList?Я где-то читал о нулях, вызывающих проблемы, но я впервые имею дело с массивами, поэтому я не знаком с предметом.В любом случае, вот мой код:

    import java.util.*;

    public class TicTacToe {

    public static void main(String[] args) {
    newBoard();
    ******************System.out.println(mark(1));************
    System.out.println(mark(5));
    System.out.println(mark(9));
   }

 // Creates a blank board.
 public static ArrayList<String> newBoard() {
  ArrayList<String> board = new ArrayList<String>(8);
  return board;
 }

 // Returns true if the square has been marked.
 public static boolean isMarked(int numberOfSquare) {
  if (numberOfSquare > 9 || numberOfSquare < 1) {
   throw new IllegalArgumentException("Input a valid square number.");
  }
  ************if (newBoard().get(numberOfSquare - 1) == null) {***********
   return false;
  } else
   return true;
 }

 // Returns the number of moves that have been made.
 public static int moveCount() {
  return countMove();
 }

 // If called, adds 1 to number of moves.
 public static int countMove() {
  int moveNumber = 0;
  moveNumber++;
  return moveNumber;
 }

 // Checks for a win at the specified array location and player (X or O).
 public static boolean checkForWin(int x, int y, int z, int player) {
  if (player == 0) {
   return (newBoard().get(x)).equals("O")
     && (newBoard().get(y)).equals("O")
     && (newBoard().get(y)).equals("O");
  } else {
   return (newBoard().get(x)).equals("O")
     && (newBoard().get(y)).equals("O")
     && (newBoard().get(y)).equals("O");
  }
 }

 // Places an X or O on the specified square.
 public static boolean mark(int markSquareNumber) {
  if (markSquareNumber > 9 || markSquareNumber < 1) {
   throw new IllegalArgumentException("Input a valid square number.");
  }
  ***********if (isMarked(markSquareNumber)) {*******************
   throw new IllegalArgumentException("Square is already marked.");
  }
  if (moveCount() % 2 != 0) {
   newBoard().add(markSquareNumber - 1, "X");
   countMove();
  } else {
   newBoard().add(markSquareNumber - 1, "O");
   countMove();
  }
  if (checkForWin(0, 1, 2, 1) || checkForWin(3, 4, 5, 1)
    || checkForWin(6, 7, 8, 1)) {
   System.out.println("Player-X just won horizontally!");
   return true;
  } else if (checkForWin(0, 3, 6, 1) || checkForWin(1, 4, 7, 1)
    || checkForWin(2, 5, 8, 1)) {
   System.out.println("Player-X just won vertically!");
   return true;
  } else if (checkForWin(0, 4, 5, 1) || checkForWin(2, 4, 6, 1)
    || checkForWin(0, 4, 8, 1)) {
   System.out.println("Player-X just won diagonally!");
   return true;
  }
  if (checkForWin(0, 1, 2, 0) || checkForWin(3, 4, 5, 0)
    || checkForWin(6, 7, 8, 0)) {
   System.out.println("Player-O just won horizontally!");
   return true;
  } else if (checkForWin(0, 3, 6, 0) || checkForWin(1, 4, 7, 0)
    || checkForWin(2, 5, 8, 0)) {
   System.out.println("Player-O just won vertically!");
   return true;
  } else if (checkForWin(0, 4, 5, 0) || checkForWin(2, 4, 6, 0)
    || checkForWin(0, 4, 8, 0)) {
   System.out.println("Player-O just won diagonally!");
   return true;
  } else
   return false;
 }
}

Я просто поставил целую кучу звездочек по строкам, которые возникли в трассировке стека.Если кто-то может указать, где я иду не так, это было бы великолепно, спасибо!

Хорошо, вот решение, которое я придумала после всего вашего замечательного вклада: (Пожалуйста, используйте это только в образовательных и справочных целях, я не хочу, чтобы мой профессор оралты в моем классе CS1410 и копируешь меня !!!!)

//Written by JTN for Assignment7.3- CS1410; October 2010. 
import java.util.*;

public class TicTacToe {
private static int moveNumber = 0;
private static ArrayList<String> board = new ArrayList<String>(8);
    public static void main(String[] args) {
        newBoard();
        mark(1);mark(2);
        mark(5);mark(3);
        mark(9);
        boardString();
    }
    // Returns the number of moves that have been made.
    public static int moveCount() {
        return (countMove()-1);
    }

    // If called, adds 1 to number of moves.
    public static int countMove() {
        moveNumber= moveNumber + 1;
        return moveNumber;
    }
    // Creates a blank board.
    public static ArrayList<String> newBoard() {
        for (int i = 0; i <= 8; i++)
            board.add("_");
        return board;
    }

    // Returns true if the square has been marked.
    public static boolean isMarked(int numberOfSquare) {
        if (numberOfSquare > 9 || numberOfSquare < 1) {
            throw new IllegalArgumentException("Input a valid square number.");
        }
        if ((board.get(numberOfSquare - 1)).equals("_")) {
            return false;
        } else
            return true;
    }



    // Checks for a win at the specified array location and player (X or O).
    public static boolean checkForWin(int x, int y, int z, int player) {
        if (player == 0) {
            return     (board.get(x)).equals("O")
                    && (board.get(y)).equals("O")
                    && (board.get(z)).equals("O");
        } 
        else {
            return     (board.get(x)).equals("X")
                    && (board.get(y)).equals("X")
                    && (board.get(z)).equals("X");
        }
    }

    // Places an X or O on the specified square.
    public static boolean mark(int markSquareNumber) {
        if (markSquareNumber > 9 || markSquareNumber < 1) {
            throw new IllegalArgumentException("Input a valid square number.");
        }
        if (isMarked(markSquareNumber)) {
            throw new IllegalArgumentException("Square is already marked.");
        }       
        if ((countMove() % 2) == 0){
            board.set(markSquareNumber - 1, "O");
        }
        else {
            board.set(markSquareNumber - 1, "X");
        } 

        if (checkForWin(0, 1, 2, 1) || checkForWin(3, 4, 5, 1)
                || checkForWin(6, 7, 8, 1)) {
            System.out.println("Player-X just won horizontally!");
            return true;
        } else if (checkForWin(0, 3, 6, 1) || checkForWin(1, 4, 7, 1)
                || checkForWin(2, 5, 8, 1)) {
            System.out.println("Player-X just won vertically!");
            return true;
        } else if (checkForWin(0, 4, 5, 1) || checkForWin(2, 4, 6, 1)
                || checkForWin(0, 4, 8, 1)) {
            System.out.println("Player-X just won diagonally!");
            return true;
        }
         else if (checkForWin(0, 1, 2, 0) || checkForWin(3, 4, 5, 0)
                || checkForWin(6, 7, 8, 0)) {
            System.out.println("Player-O just won horizontally!");
            return true;
        } else if (checkForWin(0, 3, 6, 0) || checkForWin(1, 4, 7, 0)
                || checkForWin(2, 5, 8, 0)) {
            System.out.println("Player-O just won vertically!");
            return true;
        } else if (checkForWin(0, 4, 5, 0) || checkForWin(2, 4, 6, 0)
                || checkForWin(0, 4, 8, 0)) {
            System.out.println("Player-O just won diagonally!");
            return true;
        } else
            return false;
    }

    public static String boardString(){
        String row1 = board.get(0)+"|"+board.get(1)+"|"+board.get(2);
        String row2 = board.get(3)+"|"+board.get(4)+"|"+board.get(5);
        String row3 = board.get(6)+"|"+board.get(7)+"|"+board.get(8);
        System.out.println(row1);
        System.out.println(row2);
        System.out.println(row3);
        return row1+row2+row3;
    }
}

Ответы [ 8 ]

8 голосов
/ 28 октября 2010

Эта строка

ArrayList<String> board = new ArrayList<String>(8);

не будет создавать массив из 8 строк (или 9 строк по этому вопросу, если это было намерение).Он создаст ArrayList с начальной емкостью из 8 элементов, но размером 0.

После того, как вы создали ArrayList для платы, вам нужно будет заполнить ее элементами, используяadd -метод.Попробуйте сделать что-то вроде:

public static ArrayList<String> newBoard() {
    ArrayList<String> board = new ArrayList<String>(8);
    for (int i = 0; i < 9; i++)
        board.add("");
    return board;
}

В сообщении Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 говорится, что вы пытаетесь получить доступ к 0-му элементу в списке длиной 0 (в списке без элементов).

Кроме того, следующая строка:

newBoard().add(markSquareNumber - 1, "X");

должна быть, вероятно,

newBoard().set(markSquareNumber - 1, "X");
2 голосов
/ 28 октября 2010

Со стены неформатированного кода, я думаю, я знаю вашу проблему.

public static ArrayList newBoard() { 
    ArrayList board = new ArrayList(8); 
    return board; 
}

Ничего не инициализируется в массиве.В настоящее время он пуст с 0 объектами.Это то, что вы хотите.

public static ArrayList newBoard() { 
    ArrayList<String> board = new ArrayList<String>();
    for (int i = 0; i < 9; i++) {
        board.add("");
    }
    return board; 
}

Я спрашиваю, почему вы не просто используете String[], и в этом случае new String[9] создаст 9 реальных строк.

И, кстати, у доски Tic Tac Toe 9 квадратов, я не знаю, что вы создали ее только с 8.

2 голосов
/ 28 октября 2010

Похоже, что в списке нет начальной популяции.Вы пытаетесь получить доступ к элементам, которые не существуют.

1 голос
/ 28 октября 2010

ArrayList - это динамическая структура.Даже если вы создадите «размер» при создании, он не будет заполнять массив.Если вы хотите, вы можете заполнить его самостоятельно или использовать простой массив.

Другое дело, ваша функция countMove () всегда возвращает 1. Поскольку вы устанавливаете 0 и также применяете ++ OP к 0.Если вы хотите такое поведение, просто верните 1

Надеюсь, это поможет.Приветствия.

0 голосов
/ 28 октября 2010

Помимо указанной проблемы, вы, кажется, каждый раз вызываете метод newBoard(), создавая новый ArrayList, который на самом деле не будет иметь ничего, как люди говорили выше.Это не имеет смысла делать это.Вы, вероятно, хотите иметь один объект на доске, чтобы проверить, выиграл ли игрок.

0 голосов
/ 28 октября 2010
newBoard().get(numberOfSquare - 1) == null)

Каждый раз, когда вы вызываете метод newBoard(), вы создаете новый объект ArrayList без элемента.Если вы попытаетесь получить что-то на пустом ArrayList, вы получите IndexOutOfBoundsException.

0 голосов
/ 28 октября 2010

Вы вызываете функцию newBoard() каждый раз, когда пытаетесь получить элемент из ArrayList<String>. Это будет возвращать пустой ArrayList<String> каждый раз.

Вам нужно инициализировать список, а затем вызвать функцию get для этой переменной. Другие ответы объясняют это.

0 голосов
/ 28 октября 2010

Для фиксированного размера массива, как у вас здесь, я не уверен, почему вы используете ArrayList, а не просто String[] массив? Если вы инициализируете свой массив с помощью:

String[] board = new String[9];

После этого вы сможете получить значение любого квадрата, не беспокоясь о том, что он находится за пределами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...