Java ArrayIndexOutOfBounds Error

2020-05-06 08:54发布

问题:

So I have an array Canvas[256][256] that has a random index Canvas[r][r] (r being random) set to 1. I then want to loop through the array to see exactly which index is not 0, and then pick a random spot (above, below, left, right) and set that one to 1 as well. It works perfectly fine through the first loop, but then gives me an array out of bounds error after that.

public static void checkPopulation() {
    for(int x = 0; x < Canvas.length; x++) {
        for(int y = 0; y < Canvas.length; y++) {
            if(Canvas[x][y] != 0) {
                particleDiffusion(x, y);
            }
        }
    }

}

public static void particleDiffusion(int x, int y) {
    Random r = new Random();
    if(r.nextInt(3) == 0) {
        Canvas[x+1][y] = 255;
    } else if(r.nextInt(3) == 1) {
        Canvas[x][y+1] = 255;
    } else if(r.nextInt(3) == 2) {
        Canvas[x-1][y] = 255;//THIS IS WHERE ERROR IS POINTING
    } else if(r.nextInt(3) == 3) {
        Canvas[x][y-1] = 255;
    }
    if(stepsTaken < diffusionStep) {
        checkPopulation();
    } else {
        System.out.println("done");
        return;
    }
}

can somebody help me with what I am doing wrong? And why it loops through once and then gives the error?

回答1:

Alright, let's walk through all your problems one by one.

  1. The indices. This is obvious and I won't discuss it further.

  2. checkPopulation() and particleDiffusion() recursively invoke each other. Since neither stepsTaken or diffusionStep are modified in the code path you will eventually see a StackOverflow. You don't seem to need to use recursion for this, why not use a loop instead? I'm assuming you have an initial call to checkPopulation(), so how about replacing it with:

    for (int stepsTaken = 0; stepsTaken < diffusionStep; stepsTaken++) {
        checkPopulation();
    }
    

    Right now, at a high level, your methods look like

    main() {
        checkPopulation();
    }
    
    checkPopulation() {
        ...
        particleDiffusion();
    }
    
    particleDiffusion() {
        ...
        if (stepsTaken < diffusionStep) {
            checkPopulation();
        }
    }
    

    With the change, it now looks like

    main() {
        for (int stepsTaken = 0; stepsTaken < diffusionStep; stepsTaken++) {
            checkPopulation();
        }
    }
    
    checkPopulation() {
        ...
        particleDiffusion();
    }
    
    particleDiffusion() {
        ...
    }
    
  3. Calling r.nextInt(3) == x multiple times does not distribute the probability across the four directions evenly. There's no guarantee any of the four cases will actually be successful. Save the result of r.nextInt(3) in a variable and then do the comparison on that variable.



回答2:

You check if x and y are less than Canvas.length, then you use x+1 and y+1 as array indexes, that's the reason. The fixed code is below.

public static void checkPopulation() {
    for(int x = 0; x < Canvas.length; x++) {
        for(int y = 0; y < Canvas.length; y++) {
            if(Canvas[x][y] != 0) {
                particleDiffusion(x, y);
            }
        }
    }
}

public static void particleDiffusion(int x, int y) {
    Random r = new Random();
    if(r.nextInt(3) == 0) {
        if( x+1 < Canvas.length)
            Canvas[x+1][y] = 255;
    } else if(r.nextInt(3) == 1) {
        if( y+1 < Canvas.length)
            Canvas[x][y+1] = 255;
    } else if(r.nextInt(3) == 2) {
        if( x > 0)
            Canvas[x-1][y] = 255;//THIS IS WHERE ERROR IS POINTING
    } else if(r.nextInt(3) == 3) {
        if( y > 0)
            Canvas[x][y-1] = 255;
    }
    if(stepsTaken < diffusionStep) {
        checkPopulation();
    } else {
        System.out.println("done");
        return;
    }
}

Edit: Also you should check x-1 and y-1 are not negative.



标签: java arrays