0

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?

2
  • Have you stepped through it with a debugger? What happens when x = 0 at the line you indicated? Commented Sep 9, 2015 at 17:24
  • Are you sure that you get square 2-d array..? Commented Sep 9, 2015 at 17:32

2 Answers 2

5

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.

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

3 Comments

I had already tried that, and it gives me a stackoverflow error.
@Tyson: Then that's a different problem... and probably one related to the fact that you don't appear to change stepsTaken or diffusionStep anywhere in the code... how do you expect it to stop recursing?
I do change it, every time checkPopulation gets called stepsTaken++ I just didn't paste that part.
2

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.

3 Comments

Everytime particleDiffusion is called, stepsTaken++.
@Tyson Sure. If diffusionStep is large you'll still have a StackOverflow. Using a loop solves this completely and is clearer.
I put all of this inside of a loop that loops through diffusionStep? So completely eliminate particleDiffusion and loop through both at the same time?

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.