Reputation: 638
I am the beginnings of writing a tic-tac-toe game. I just ran it and got the following stack trace:
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)
I suspect it is a problem with the way I have the ArrayList setup? I read somewhere about nulls causing problems, but this is my first time dealing with arrays, so I'm not to familiar with the subject. Anyhow, here is my code:
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;
}
}
I just put a whole bunch of asterisks by the lines that came up in the stack-trace. If anyone could point out where I am going wrong that would be splendid, thanks!
Ok, here is the solution that I came up with after all your wonderful input: (Please only use this for educational and reference purposes, I don't want to get yelled at by my professor if you are in my CS1410 class and you copy me!!!!)
//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;
}
}
Upvotes: 0
Views: 1134
Reputation: 5327
newBoard().get(numberOfSquare - 1) == null)
Every time you call the newBoard()
method, you create a new ArrayList
object with no element.
If you try to get something on an empty ArrayList
, you'll get an IndexOutOfBoundsException
.
Upvotes: 0
Reputation: 263
Besides the stated problem, you seem to be calling a newBoard()
method each time, creating a new ArrayList
, which wouldn't actually have anything as people have stated above. It doesn't make sense to do that. You probably want to have a single board object to check whether a player has won.
Upvotes: 0
Reputation: 2265
ArrayList is a dinamic structure. Even if you put a "size" when you create it, it will not fill the arraylist. If you want you can fill it by yourself or use a simple Array.
Other thing, your countMove() function is always returning 1. Because you are setting 0 and appling the ++ OP to 0 as well. If you want that behavior just return 1
Hope this helps. Cheers.
Upvotes: 1
Reputation: 421020
This line
ArrayList<String> board = new ArrayList<String>(8);
will not create an array of 8 strings (or 9 strings for that matter, if that was the intention). It will create an ArrayList with initial capacity of 8 elements, but of size 0.
After you've created the ArrayList for the board, you'll have to populate it with elements using the add
-method. Try doing something like:
public static ArrayList<String> newBoard() {
ArrayList<String> board = new ArrayList<String>(8);
for (int i = 0; i < 9; i++)
board.add("");
return board;
}
The message Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
says that you're trying to access the 0th element in a list of length 0 (in a list without elements).
Furthermore, the following line:
newBoard().add(markSquareNumber - 1, "X");
should probably be
newBoard().set(markSquareNumber - 1, "X");
Upvotes: 8
Reputation: 2312
From the wall of unformatted code, I think I know your problem.
public static ArrayList newBoard() {
ArrayList board = new ArrayList(8);
return board;
}
Doesn't initialize anything in the arraylist. It is currently empty with 0 objects. This is what you want.
public static ArrayList newBoard() {
ArrayList<String> board = new ArrayList<String>();
for (int i = 0; i < 9; i++) {
board.add("");
}
return board;
}
I question why you don't just use a String[]
, in which case new String[9]
will create 9 actual Strings.
And by the way, a tic tac toe board has 9 squares, I don't know what you only created it with 8.
Upvotes: 2
Reputation: 11408
You are calling your newBoard()
function every time you try to get an element from your ArrayList<String>
. This will return an empty ArrayList<String>
every time.
You need to initialize the list and then call the get function on that variable. The other answers explain this.
Upvotes: 0
Reputation: 15063
For a fixed array size like you have here, I'm not sure why you're using an ArrayList
, and not just a simple String[]
array? If you initialize your array with:
String[] board = new String[9];
You will then actually be able to get the value of any square without having to worry about being out of bounds.
Upvotes: 0
Reputation: 17775
It looks like there is no initial population of the list. You're trying to access elements that don't exist.
Upvotes: 2