Code:
/*
* Hi, I'm writing a TicTacToe program (that is not yet finished) which
* compiled without any errors.. but when I run the code it says
* "ArrayIndexOutOfBoundsException: 49." What does this mean?
* I've tried try/catch blocks and throwing the exceptions in my methods
* but this doesn't work. Can someone please help me by explaining the problem
* and giving a solution? Thanks.
*/
import java.io.*;
public class TicTacToe {
char[][] board = new char[3][3];
BufferedReader in = new BufferedReader(new InputStreamReader(System.in) );
public TicTacToe() throws IOException {
while(!gameOver()) {
createBoard();
//Player 1
System.out.println("Which row?");
int r = in.read();
System.out.println("Which column?");
int c = in.read();
printInput(r, c, 'X');
//Player 2
System.out.println("\nWhich row?");
r = in.read();
System.out.println("Which column?");
c = in.read();
printInput(r, c, 'O');
}
}
public void createBoard() {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
board[j] = '_';
}
}
}
public void printInput(int row, int column, char input) throws ArrayIndexOutOfBoundsException {
try {
board[row][column] = input;
//line 49 below
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
System.out.print(board[j] + " ");
}
System.out.print("\n");
}
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println(e);
}
}
public boolean gameOver() {
// I am going to add conditions in later; for now I am just testing out the rest of the code.
return false;
}
public static void main(String[] args) throws IOException{
System.out.println("Tic Tac Toe\n-----------------------\n");
new TicTacToe();
}
}
Aside from being horribly ugly since you forgot to use code tags, it looks OK to me. Of course, a traceback of the failure would be nice. Also, your TicTacToe array is much too small. If you're going to be indexing it with characters, it needs to be at least [58][58], preferably more since it doesn't look like you're doing any input validation (i.e. the program will crash if you ask it for row 'z' instead of '1').
Take a look at what happens if the user inputs a number greater than 2 (or less than 0) for either the row or the column:
// first line of printInput
board[row][column] = input;
try something like this to verify the user input:
int r;
do
{
System.out.println("Which row?");
r = in.read();
}while(r < 0 || r > 2);
Quote from: K on July 31, 2005, 05:06 PMtry something like this to verify the user input:
int r;
do
{
System.out.println("Which row?");
r = in.read();
}while(r < 0 || r > 2);
Minor nit: I think he's going to have a difficult time typing NULs, and he's not going to expect needing to use ^A and ^B for rows 1 and 2. :) Try using
r = in.read() - '0';
for the actual input, along with the rest of K's code.
Thanks guys. It works now. I made my array bigger and used the do-while loops. What also was wrong was that the read() method wasn't reading my integers as I wanted them to. I made a little program to test this out...
<code>
import java.io.*;
public class ReadTest {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in) );
public ReadTest() throws IOException {
int num;
System.out.println("pick a number");
num = in.read();
System.out.println("You chose " + num + ".");
}
public static void main(String[] args) throws IOException {
new ReadTest();
}
}
</code>
When I input 1 it spat out 49! I guess this has something to do with it interpreting my input as ASCII? Is there a different class/method that interprets integers as integers?
Well, in a crude solution to this I got a class off the net called EasyReader which can be found at javamethods.com on the studentdisk. It makes user input a lot easier.
**EDIT: LOL that "html-like-stuff-in-my-java-program" must look silly. How do you use code tags (which I assume make your code go in the gray box...?)
Kp's addition to my code will fix the problem you are having. I suggest you keep your arrays at size 3, since that's all you need.
Oh, replace the < and > with [ and ] to get the totally sweet code formatting..
For the record, I believe it's bad practice to place execution code (or logic) in a constructor beyond that which is necessary to initialize a type. You do that with:
new TicTacToe();
A constructor is a method, yes, but it's a special kind of method -- one for allocating memory and initializing an object. A method such as .runGame() would be great, or even .begin().
I simply think that a constructor should be as exception-free as possible, except to reject exceptional initialization values. Since this one doesn't accept any parameters, and (should) perform no I/O, there should be no exception being thrown.
Thanks for the input everybody. Myndfyre I followed your advice about the constructor. I'm sort of new to programming so it's nice to get advice on form and "good practice." Here's the code:
/*
* Tic Tac Toe program
* by Dynobird
* Yes I know the code is ugly... I tried to make it easy to read
* How exciting, I'm using the code tags (correctly!!) for the first time!
*/
import java.io.*;
public class TicTacToe {
EasyReader in = new EasyReader();
char[][] board = new char[100][100];
int r, c;
int newGame;
public TicTacToe() {}
/****************** RUNS THE GAME ******************/
public void runGame() throws IOException {
System.out.println("Please input names");
System.out.print("Player 1: ");
String p1 = in.readLine();
System.out.print("Player 2: ");
String p2 = in.readLine();
createBoard();
while(!gameOver(newGame)) {
// Ask player 1
do {
System.out.println(p1 + ": Which row?");
r = in.readInt();
} while( r < 0 || r >2 );
do {
System.out.println(p1 + ": Which column?");
c = in.readInt();
} while( c < 0 || r > 2);
//Player 1 input and check if game is over
printInput(r, c, 'X');
if(gameOver(newGame)) {
System.out.println("\n" + p1 + " wins!");
break;
}
//Ask player 2
do {
System.out.println(p2 + ": Which row?");
r = in.readInt();
} while( r < 0 || r >2 );
do {
System.out.println(p2 + ": Which column?");
c = in.readInt();
} while( c < 0 || r > 2);
//Player 2 input and check if game is over
printInput(r, c, 'O');
if(gameOver(newGame)) {
System.out.println("\n" + p2 + " wins!");
break;
}
}
do {
System.out.println("New game? 0. No 1. Yes :: ");
int newGame = in.readInt();
if (!gameOver(newGame) ) {
new TicTacToe();
}
} while( newGame < 0 || newGame > 1);
System.out.println("\nThanks for playing. Have a nice day!");
}
/****************** PRINTS EMPTY BOARD ******************/
public void createBoard() {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
board[i][j] = '_';
System.out.print(board[i][j] + " ");
}
System.out.print("\n");
}
}
/****************** PRINTS USER INPUT ******************/
public void printInput(int row, int column, char input) throws ArrayIndexOutOfBoundsException {
board[row][column] = input;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
System.out.print(board[i][j] + " ");
}
System.out.print("\n");
}
}
/****************** CHECKS TO SEE IF GAME IS OVER ******************/
public boolean gameOver(int newGameOrNot) {
//new game yes or no?
if( newGameOrNot == 1) {
return false;
}
//rows
for(int i = 0; i < 3; i++) {
if( (board[i][0] == 'X' || board[i][0] == 'O') && (board[i][0] == board[i][1]) && (board[i][0] == board[i][2]) ) {
return true;
}
}
//columns
for(int j = 0; j < 3; j++) {
if( (board[0][j] == 'X' || board[0][j] == 'O') && (board[0][j] == board[1][j]) && (board[0][j] == board[2][j]) ) {
return true;
}
}
//diagonals
if(
( (board[0][0] == 'X' || board[0][0] == 'O') && (board[0][0] == board[1][1]) && (board[0][0] == board[2][2]) ) ||
( (board[2][0] == 'X' || board[2][0] == 'O') && (board[2][0] == board[1][1]) && (board[2][0] == board[0][2]) )
)
{
return true;
}
//if game is not over, continue while loop
else {
return false;
}
}
/****************** CALLS CONSTRUCTOR ******************/
public static void main(String[] args) throws IOException{
System.out.println("Tic Tac Toe\n-----------------------\n");
TicTacToe t3 = new TicTacToe();
t3.runGame();
}
}