Here is an n-dimensional stepper that can step in any number of dimensions in any order from any place of origin to any limits. See Test Code for an example.
public class Test {
public void test() {
int[] limits = {3, -5, 7};
int[] order = {0, 2, 1};
int[] starts = {0, 0, 0};
int[] steps = {1, -1, 2};
NDimensionalStepper nds = new NDimensionalStepper(limits, order, starts, steps);
do {
System.out.println(nds);
} while (nds.step());
}
public static void main(String args[]) {
new Test().test();
}
public static class NDimensionalStepper {
final int[] i;
final int[] starts;
final int[] steps;
final int[] limits;
final int[] order;
int d = 0;
public NDimensionalStepper(int[] limits, int[] order, int[] starts, int[] steps) {
this.i = Arrays.copyOf(starts, starts.length);
this.starts = Arrays.copyOf(starts, starts.length);
this.steps = Arrays.copyOf(steps, steps.length);
this.limits = Arrays.copyOf(limits, limits.length);
this.order = Arrays.copyOf(order, order.length);
}
public NDimensionalStepper(int[] limits, int[] order, int[] starts) {
this(limits, order, starts, defaultSteps(limits, starts));
}
private static int[] defaultSteps(int[] limits, int[] starts) {
int[] steps = new int[limits.length];
for (int i = 0; i < limits.length; i++) {
steps[i] = (int) Math.signum(limits[i] - starts[i]);
}
return steps;
}
public NDimensionalStepper(int[] limits, int[] order) {
this(limits, order, defaultStarts(limits.length));
}
private static int[] defaultStarts(int d) {
int[] starts = new int[d];
Arrays.fill(starts, 0);
return starts;
}
public NDimensionalStepper(int[] limits) {
this(limits, defaultOrder(limits.length));
}
private static int[] defaultOrder(int d) {
int[] order = new int[d];
for (int i = 0; i < d; i++) {
order[i] = d - i - 1;
}
return order;
}
public int get(int d) {
return i[d];
}
public boolean step() {
boolean stepped = false;
boolean finished = false;
while (!stepped && !finished) {
int o = order[d];
while (finished(o) && d < order.length - 1) {
o = order[++d];
}
if (d < order.length && !finished(o)) {
i[o] += steps[o];
stepped = true;
while (d > 0) {
d -= 1;
i[order[d]] = starts[order[d]];
}
} else {
finished = true;
}
}
return !finished;
}
private boolean finished(int o) {
int sign = (int) Math.signum(steps[o]);
return sign * (i[o] + steps[o]) >= sign * limits[o];
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append("{");
for (int d = 0; d < order.length; d++) {
s.append(get(d));
if (d < order.length - 1) {
s.append(",");
}
}
s.append("}");
return s.toString();
}
}
}
My equivalent tests for the three scenarios are as follows:
private void testBuild1(Build build) {
System.out.println("Build: x,y,z");
for (int x = 0; x < build.getWidth(); x++) {
for (int y = 0; y < build.getHeight(); y++) {
for (int z = 0; z < build.getLength(); z++) {
System.out.println("{" + x + "," + y + "," + z + "}");
}
}
}
int[] limits = {build.getWidth(), build.getHeight(), build.getLength()};
testNDS(new NDimensionalStepper(limits));
}
private void testBuild2(Build build) {
System.out.println("Build: z,y,x");
for (int z = 0; z < build.getLength(); z++) {
for (int y = 0; y < build.getHeight(); y++) {
for (int x = 0; x < build.getWidth(); x++) {
System.out.println("{" + x + "," + y + "," + z + "}");
}
}
}
int[] limits = {build.getWidth(), build.getHeight(), build.getLength()};
int[] order = {0,1,2};
testNDS(new NDimensionalStepper(limits, order));
}
private void testBuild3(Build build) {
System.out.println("Build: x--,y,z");
for (int x = build.getWidth(); x > 0; x--) {
for (int y = 0; y < build.getHeight(); y++) {
for (int z = 0; z < build.getLength(); z++) {
System.out.println("{" + x + "," + y + "," + z + "}");
}
}
}
int[] limits = {0, build.getHeight(), build.getLength()};
int[] order = {2,1,0};
int[] starts = {build.getWidth(), 0, 0};
int[] steps = {-1, 1, 1};
testNDS(new NDimensionalStepper(limits, order, starts, steps));
}
private void testNDS(NDimensionalStepper nds) {
System.out.println("--nds--");
do {
System.out.println(nds);
} while (nds.step());
}