• Welcome to Valhalla Legends Archive.
 

Problem with Arrays - ArrayIndexOutOfBoundsException

Started by Dynobird, July 31, 2005, 04:24 PM

Previous topic - Next topic

Dynobird

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();
    }
}


Kp

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').
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

K

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);

Kp

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.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Dynobird

#4
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...?)

K

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..

MyndFyre

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.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Dynobird

#7
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();
    }
}