Dưới đây là một bước nhảy n-chiều có thể bước vào bất kỳ số thứ nguyên nào theo thứ tự bất kỳ từ bất kỳ vị trí bắt đầu nào đến bất kỳ giới hạn nào. Xem mã thử nghiệm để biết ví dụ.
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 {
// The current positions in each dimension.
// Note that i[order[0]] is the fastest mover.
final int[] i;
// Starts.
final int[] starts;
// Steps.
final int[] steps;
// Limits.
final int[] limits;
// Order.
final int[] order;
// The (unordered) dimension we last stepped.
int d = 0;
// Full constructor.
public NDimensionalStepper(int[] limits, int[] order, int[] starts, int[] steps) {
// Should parameter check to ensure all are the same length.
// Should also check that each dimension will terminate.
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);
}
// Default steps to 1.
public NDimensionalStepper(int[] limits, int[] order, int[] starts) {
this(limits, order, starts, defaultSteps(limits, starts));
}
// Default steps - 1 Towards limits.
private static int[] defaultSteps(int[] limits, int[] starts) {
int[] steps = new int[limits.length];
for (int i = 0; i < limits.length; i++) {
// Step towrds limits.
steps[i] = (int) Math.signum(limits[i] - starts[i]);
}
return steps;
}
// Default starts to 0.
public NDimensionalStepper(int[] limits, int[] order) {
this(limits, order, defaultStarts(limits.length));
}
// Default starts - 0, 0, ...
private static int[] defaultStarts(int d) {
int[] starts = new int[d];
Arrays.fill(starts, 0);
return starts;
}
// Default order to normal.
public NDimensionalStepper(int[] limits) {
this(limits, defaultOrder(limits.length));
}
// Default order - ..., 1, 0
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;
}
// Get the current position in dimension d.
public int get(int d) {
return i[d];
}
// Take just one step. Return false if cant.
public boolean step() {
boolean stepped = false;
boolean finished = false;
while (!stepped && !finished) {
// Which dimension should be stepped (depends on order).
int o = order[d];
// Can we step in the current dimension?
while (finished(o) && d < order.length - 1) {
// Reached a limit! - Move up one dimension.
o = order[++d];
}
if (d < order.length && !finished(o)) {
// Step it.
i[o] += steps[o];
stepped = true;
// Zero all lower dimensions.
while (d > 0) {
d -= 1;
i[order[d]] = starts[order[d]];
}
} else {
// Got to the last without finding one below limit. Finished!
finished = true;
}
}
return !finished;
}
// Equal or passed the limits.
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();
}
}
}
xét nghiệm của tôi về sự tương đương của ba kịch bản của bạn trông giống như:
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());
}
Sử dụng vòng lặp để thay thế. Chương trình của bạn được mã hóa cứng để lặp qua chúng như 'iter1',' iter2', 'iter3', nhưng trước khi nhập các vòng lặp, hãy thiết lập chúng theo đầu vào của người dùng. – aioobe
Điều đó có thể hoạt động. Tôi chỉ cần thiết lập một số bộ sưu tập cho các coords xyz và đảo ngược chúng nếu tôi cần theo hướng ngược lại. – Antonio
@aioobe nếu đây là câu trả lời tôi sẽ bỏ phiếu bầu chọn này! –