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?
Alright, let's walk through all your problems one by one.
The indices. This is obvious and I won't discuss it further.
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() {
...
}
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.
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.