1

What I am doing is creating a command line "game" where there is a 3x3 grid (Array) where you can move a "1" through it by typing the direction (up, down, left, right).

For example:

0 0 0

0 1 0

0 0 0

I've made it so if the 1 is on the edge of the array it is not allowed to move out of the boundaries (read: resulting in an out of index error).

I'm completely lost as whenever I try to move right, I receiving the following:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at Logic.setMove(Logic.java:87)
at Logic.getMove(Logic.java:10)
at GridGameMain.main(GridGameMain.java:13)

Here's my code:

public class GridGameMain {
static int[][] board = new int[3][3];
public static void main(String[] args){

    board[(int) (Math.random() * 2.5)][(int) (Math.random() * 2.5)] = 1;
    for (int i =0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
        System.out.print(" " + board[j][i]);
        }
        System.out.println("");
        }
    Logic l = new Logic();
    l.getMove();

}

}


import java.util.Scanner;

public class Logic extends GridGameMain{
void getMove(){     //takes user input then calls setMove

    String direction;  //string to hold the direction
    Scanner user_input = new Scanner(System.in);   
    direction = user_input.next();    
    Logic l = new Logic();      
    l.setMove(direction);        

}
void setMove(String direction){ //called when user presses enter upon typing a move
    Logic l = new Logic();

    if(direction.equals("up")){

        if(board[0][0] == 1 || board[1][0] == 1 || board[2][0] == 1 ){

            System.out.println("Invalid move!");

            l.getMove();

        }else{
        for(int a = 0; a < 3; a++){
            for(int b = 0; b < 3; b++){
                if(board[a][b] == 1){
                    board[a][b-1] = 1;
                    board[a][b] = 0;
                    break;
                }
            }
        }
        l.printBoard();
        System.out.println("you moved up");
        l.getMove();
        }
    }

    if(direction.equals("down")){           
        if(board[0][2] == 1 || board[1][2] == 1 || board[2][2] == 1 ){
            System.out.println("Invalid move!");
            l.getMove();
        }else{
            for(int a = 0; a < 3; a++){
                for(int b = 0; b < 3; b++){
                    if(board[a][b] == 1){
                        board[a][b+1] = 1;
                        board[a][b] = 0;
                        break;
                    }
                }
            }
            l.printBoard();
        System.out.println("you moved down");
        l.getMove();
        }
    }
    if(direction.equals("left")){
        if(board[0][0] == 1 || board[0][1] == 1 || board[0][2] == 1 ){
            System.out.println("Invalid move!");
            l.getMove();
        }else{
            for(int a = 0; a < 3; a++){
                for(int b = 0; b < 3; b++){
                    if(board[a][b] == 1){
                        board[a-1][b] = 1;
                        board[a][b] = 0;
                        break;
                    }
                }
            }
            l.printBoard();

        System.out.println("you moved left");
        l.getMove();
        }
    }
    if(direction.equals("right")){
        if(board[2][0] == 1 || board[2][1] == 1 || board[2][2] == 1 ){
            System.out.println("Invalid move!");
            l.getMove();
        }else{
            for(int a = 0; a < 3; a++){
                for(int b = 0; b < 3; b++){
                    if(board[a][b] == 1){
                        board[a+1][b] = 1;
                        board[a][b] = 0;
                        break;
                    }
                }
            }

        l.printBoard();
        System.out.println("you moved right");
        l.getMove();
        }
    }
}
void printBoard(){
    for (int i =0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
        System.out.print(" " + board[j][i]);
        }
        System.out.println("");
        }
}
}

I'm just not sure why I can't move right when I can move up, down, and left just fine. Please tell me I'm not crazy!

cmcdaniels
  • 145
  • 1
  • 3
  • 13
  • by the way, why is Logic extending GridGameMain ? – Kousalik Jul 12 '12 at 06:32
  • I'm gonna get chewed out for saying this, but this was a really quick thing I just thought of and I extended it to have access to the board array values. – cmcdaniels Jul 12 '12 at 06:34
  • aside of your exception, you are creating with every recursive call of `setMove` a new `Logic` object. You should only create one Logic object, while using `this.getMove()` and `this.setMove()` inside of your class. – Herm Jul 12 '12 at 06:35
  • and why are you still creating new instance of Logic, instead of calling this.getMove(); – Kousalik Jul 12 '12 at 06:37
  • You're getting answers to your specific question. Now, side topic, and purely as a suggestion: you might have an easier time if you designed this so that you store the position of the 1 and simply draw a board whenever you need to. It will also be more efficient when dealing with larger boards. – Miquel Jul 12 '12 at 06:46
  • Thanks for the advice! I know that was probably the most atrocious code you have ever seen, but I'm still terrible at programming. I am planning to expand this idea eventually into a game like checkers, however, for now I just wanted to see how to move a "piece" on a board. Also, what do you mean as far as storing then re-drawing? – cmcdaniels Jul 12 '12 at 06:52

5 Answers5

2

On your move right:

        for(int a = 0; a < 3; a++){
            for(int b = 0; b < 3; b++){
                if(board[a][b] == 1){
                    board[a+1][b] = 1;  // what if a is 2??
                    board[a][b] = 0;
                    break;
                }
            }

When a is 2, accessing board[a+1][b] is accessing board[3][b]. On a 3*3 board, that's beyond bounds.

Edit: the problem is due to the fact that after you move the 1, you continue the outer loop - but without the initial bounds check. So after the 1 is moved from the central column to the right one, you try to move it again. This only happens on a right move due to the why you loop.

There are two easy solutions:

  1. Use some flag to make sure you break out of the outer loop as well, or better yet -
  2. Change the bounds of the fors according to what you're actually going to check. If you're not going to move a 1 that is on column #2, you can have a loop between 0 and 1. No reason to go up to 2, if you're never going to make it move from that point. Same goes to all other moves - change the appropriate bounds from < 3 to < 2.
Eran
  • 21,632
  • 6
  • 56
  • 89
  • If you look a little bit above that for statement, you can see I have a if statement check to see if anything on the right edge equals 1. I'm not having a problem with going any other direction. – cmcdaniels Jul 12 '12 at 06:29
  • Yes this works, thanks! I completely overlooked that part. =/ – cmcdaniels Jul 12 '12 at 06:54
2

I think the trouble is, you check to make sure the 1 is not on the far right, and then you start shifting things right. That means that, if your 1 was on the column 0, it's moved to column 2, then at the next and last iteration, it's moved to column 3.

Also, are you sure this doesn't happen when you go down? This doesn't happen going down because, as @Keppil says, you break out of the "rows" (relevant) loop, while going right, you break out of the columns one, which is not what you wanted.

Also, you can use tags to break out of whatever loop you want. Here's how.

Community
  • 1
  • 1
Miquel
  • 15,405
  • 8
  • 54
  • 87
  • OP performs a `break` on the inner loop, so this can only happen when the outer loop variable is incremented, eg going right. – Keppil Jul 12 '12 at 06:42
  • @Keppil ah yes, you're right. So, this only happens going right because you happened to choose to go loop first through columns and then trhough rows – Miquel Jul 12 '12 at 06:45
  • Ahh Miquel, thanks A LOT for that link. I just finished Head First Java and never encountered the tag system, so this will come in handy! :D – cmcdaniels Jul 12 '12 at 07:03
  • @EnviousNoob I've been coding in Java for years, and I only found that link some months back myself ;) – Miquel Jul 12 '12 at 07:11
2

The problem is that you are moving the "1" from left to right, so since you break the first for, you don't break the second one, so it keep moving the "1", until it is put outside the array (ArrayIndexOutOfBoundsException).

An example to solve it:

            boolean found = false;
            for(int a = 0; a < 3; a++){                 
                for(int b = 0; b < 3; b++){                     
                    if(board[a][b] == 1){                         
                        board[a+1][b] = 1;                         
                        board[a][b] = 0;
                        found = true;
                        break;                     
                    }
                    if(found){
                        break;
                    }
                }             
            }
raven1981
  • 1,415
  • 1
  • 16
  • 20
1

The break; inside your for-loops seems to interrupt only the inner for-loop. after breaking the for(int b = 0; b < 3; b++){ .. }, there is no reason for the outer loop to stop.

Your loop finds the 1 at [1][1] and shifts it to the right. then it breaks the inner loop. Nevertheless it calls the inner loop for a=2, where your 1 is now. He tries to shift again.. and fails with exception.

Herm
  • 2,956
  • 19
  • 32
0

I believe you should be getting an error when you go to the right. The reason is because when you shift one to the right, you break and then you increment a, but you do not check that it went out of bounds again. Once the 'b' loop finishes and then increments 'a' then it will register it as having a value of 1 and move it once more to the right. This keeps going until it is out of bounds. An easy way to correct your code is to just reverse your loops so the outer loop is incrementing 'b' and the inner loop is incrementing 'a'.

Alex
  • 146
  • 6