0

I am making a 3x3 grid type application, and I want to recall the button pressed to change it by adding a for loop. However, I get the exception "java.lang.ArrayIndexOutOfBoundsException: length=3; index=3" because the for loop is weird. Could anyone figure out this for me? I am new to java and programming in general.

Code:

public int j = 1;
public int i = 1;
public final int[][] buttons = new int[][] {
        {R.id.top_left_button, R.id.top_center_button, R.id.top_right_button},
        {R.id.left_button, R.id.center_button, R.id.right_button},
        {R.id.bottom_left_button, R.id.bottom_center_button, R.id.bottom_right_button}};
private Button lastButton;

public void setPlayer(Button button, int x, int y){
    button.setText("!");
    lastButton = (Button)findViewById(buttons[x][y]);
    lastButton.setText(" ");
    lastButton = button;
}
@Override


protected void onCreate(Bundle savedInstanceState) {


    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game);


    ctx = this;

    final GameEngine game = new GameEngine();
    lastButton = (Button)findViewById(R.id.center_button);
    for (i = 0; i < buttons.length; i++) {
        for (j = 0; j < buttons[i].length; j++) {
            final Button button = (Button)findViewById(buttons[i][j]);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Button b = (Button)v;
                    int x = i;
                    int y = j;
                    setPlayer(b, x , y);
                }
            });
        }
    }
4
  • Try this public final int[][] buttons = new int[3][3] now assign id's to array . Commented Jan 15, 2015 at 3:37
  • 2
    @sonukumar: What difference would it make? Commented Jan 15, 2015 at 3:53
  • @Rohit5k2 check McGee answer for more details . Commented Jan 15, 2015 at 4:19
  • I have read that answer but your comment says something different. Putting size is not necessary when you are assigning value right then Commented Jan 15, 2015 at 4:26

2 Answers 2

3

The question you need to ask is: what are the values of i and j when the button is clicked?

The answer for i is: buttons.length. Because that's the value you left i at when you left the loop.

This should work:

for (i = 0; i < buttons.length; i++) {
        final int iCopy = i;  
        for (j = 0; j < buttons[i].length; j++) {
            final Button button = (Button)findViewById(buttons[i][j]);
            final int jCopy = j;
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Button b = (Button)v;
                    int x = iCopy;
                    int y = jCopy;
                    setPlayer(b, x , y);
                }
            });
        }
    }

The reason this will work is, because of the scoping, you are creating a new instance of iCopy with each outer iteration, and a new instance of jCopy with each inner iteration. Each anonymous OnClickListener implementation will now be using the appropriate copies.

Sign up to request clarification or add additional context in comments.

1 Comment

Good catch! However, IMO, a better solution is to declare i and j as local variable unless the value of i and j is used later, which I very much doubt
1

You should declare and initialize your array like this:

public final int[][] buttons = {
        {R.id.top_left_button, R.id.top_center_button, R.id.top_right_button},
        {R.id.left_button, R.id.center_button, R.id.right_button},
        {R.id.bottom_left_button, R.id.bottom_center_button, R.id.bottom_right_button}};

In your loops you can just initalize new i and j variables like this:

for (int i = 0; i < buttons.length; i++) {
    for (int j = 0; j < buttons[i].length; j++) {
    ...
    ...
    }
}

No need to declare them at the top of your activity.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.