You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java星系模拟代码位移异常求助:轻量星系无法向重星系移动

星系吸引模拟程序移动问题排查

我正在开发一个星系相互吸引的模拟程序,核心规则是质量更小的星系会向质量更大、距离更近的星系移动。但目前网格中代表星系的数字无法正确移动,期望数字2能移动到数字8的位置,以下是完整代码,请帮忙排查问题:

import java.io.IOException;

public class galaxias_char {
    public static void main(String... args) throws InterruptedException, IOException {

        int rows = 10;
        int cols = 10;
        int depth = 10;

        char[][][] grid = new char[rows][cols][depth];

        InicializarTablero(grid);

        grid[0][2][2] = '8';
        grid[0][8][7] = '2';

        for(int gen = 1; gen <= 50; gen++){
            new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
            System.out.println("\n--> [Generación " + gen + "]");
            imprimirTablero(grid);

            // logica de desplazamiento y demás:
            for (int i = 0; i < grid.length; i++) {
                for (int j = 0; j < grid[i].length; j++) {
                    for (int k = 0; k < grid[i][j].length; k++) {

                        if(calcularDistancia(grid, i, j, k) != Integer.MAX_VALUE){
                            int distanciaMásCercana = calcularDistancia(grid, i, j, k);
                            desplazamiento(grid, distanciaMásCercana, i, j, k);
                            System.out.println("--&gt; Distancia: " + distanciaMásCercana);
                        }
                    }
                }
            }

            Thread.sleep(1000);
        }
    }

    // inicialización de tablero vacío con puntos.
    public static void InicializarTablero(char[][][] grid) {
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                for (int k = 0; k < grid[i][j].length; k++) {
                    grid[i][j][k] = '.';
                }
            }
        }
    }

    // imprimir el tablero porque los arrays apestan:
    public static void imprimirTablero(char[][][] grid) {
        for (int capa = 0; capa < grid.length; capa++) {

            System.out.println("\n--> {Capa: " + capa + "}");

            for (int fila = 0; fila < grid[capa].length; fila++) {

                for (int columna = 0; columna < grid[capa][fila].length; columna++) {
                    System.out.print(grid[capa][fila][columna] + " ");
                }

                System.out.println();
            }
        }
    }

    // hacer la función que devuelve la distancia a la que esta un valor de su destino:
    public static int calcularDistancia(char[][][] grid, int x, int y, int z){

        int distanciaMásCercana = Integer.MAX_VALUE;

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                for (int k = 0; k < grid[i][j].length; k++) {
                    if(grid[i][j][k] != '.' && grid[x][y][z] != '.' && Character.getNumericValue(grid[i][j][k]) > Character.getNumericValue(grid[x][y][z])){

                        int distancia = Math.abs(x - i) + Math.abs(y - j) + Math.abs(z - k);

                        if(distancia < distanciaMásCercana){
                            distanciaMásCercana = distancia;
                        }
                    }
                }
            }
        }

        return distanciaMásCercana;
    }

    // función de desplazamiento (parte critica):
    public static void desplazamiento(char[][][] grid, int distancia, int x, int y, int z){
        int[] dx = { -1, -1, -1, 0, 0, 1, 1, 1, 0, 0, 0, 0 };
        int[] dy = { -1, 0, 1, -1, 1, -1, 0, 1, 0, 0, 0, 0 };
        int[] dz = { 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0 };

        int newX = x;
        int newY = y;
        int newZ = z;

        for(int i = 0; i < 12; i++){

            int X = newX + dx[i];
            int Y = newY + dy[i];
            int Z = newZ + dz[i];

            if (X >= 0 && X < grid.length && Y >= 0 && Y < grid[0].length && Z >= 0 && Z < grid[0][0].length){

                int newDistance = Math.abs(newX - X) + Math.abs(newY - Y) + Math.abs(newZ - Z);

                if (newDistance < distancia && grid[X][Y][Z] == '.') {
                    distancia = newDistance;
                    newX = X;
                    newY = Y;
                    newZ = Z;
                }

                System.out.println("---&gt; newDistance: " + newDistance);
            }
        }

        grid[newX][newY][newZ] = grid[x][y][z];
        grid[x][y][z] = '.';
    }
}

核心问题分析

  • 位移逻辑方向判断完全错误:desplazamiento方法中计算newDistance的逻辑,是比较候选位置到当前临时位置的距离,而非到目标星系的距离,根本无法实现向目标靠近的效果。
  • 未记录目标星系坐标:calcularDistancia仅返回了最近大质量星系的距离,但没有记录其具体坐标,导致位移时不知道要往哪个方向移动。
  • 同一代内重复处理星系:主循环直接遍历原网格并修改,一个星系移动后,后续循环会再次处理新位置的它,导致同一代内多次移动,不符合模拟规则。
  • 方向数组冗余:dx/dy/dz包含多个(0,0,0)无效项,浪费计算资源。

修复方案

1. 修改目标查找逻辑,返回目标坐标

替换原calcularDistancia方法,返回目标星系的坐标和距离:

// 返回数组格式:[目标x, 目标y, 目标z, 距离],无目标则返回null
public static int[] encontrarObjetivo(char[][][] grid, int x, int y, int z){
    int distanciaMinima = Integer.MAX_VALUE;
    int[] objetivo = null;
    int masaActual = Character.getNumericValue(grid[x][y][z]);
    
    if(masaActual == -1) return null; // 跳过空位置
    
    for (int i = 0; i < grid.length; i++) {
        for (int j = 0; j < grid[i].length; j++) {
            for (int k = 0; k < grid[i][j].length; k++) {
                int masaObjetivo = Character.getNumericValue(grid[i][j][k]);
                if(grid[i][j][k] != '.' && masaObjetivo > masaActual){
                    int distancia = Math.abs(x - i) + Math.abs(y - j) + Math.abs(z - k);
                    if(distancia < distanciaMinima){
                        distanciaMinima = distancia;
                        objetivo = new int[]{i, j, k, distancia};
                    }
                }
            }
        }
    }
    return objetivo;
}

2. 重写位移逻辑,基于目标坐标移动

根据目标坐标计算移动方向,每次朝目标移动一格:

public static void desplazamiento(char[][][] grid, int[] objetivo, int x, int y, int z){
    int objX = objetivo[0];
    int objY = objetivo[1];
    int objZ = objetivo[2];
    
    // 计算每个轴的移动方向(-1=靠近目标方向,1=远离,0=不动)
    int dirX = Integer.compare(objX, x);
    int dirY = Integer.compare(objY, y);
    int dirZ = Integer.compare(objZ, z);
    
    int newX = x + dirX;
    int newY = y + dirY;
    int newZ = z + dirZ;
    
    // 检查新位置合法且为空
    if (newX >= 0 && newX < grid.length && 
        newY >= 0 && newY < grid[0].length && 
        newZ >= 0 && newZ < grid[0][0].length &&
        grid[newX][newY][newZ] == '.') {
        grid[newX][newY][newZ] = grid[x][y][z];
        grid[x][y][z] = '.';
    }
}

3. 修改主循环,先收集移动操作再统一执行

避免同一代内重复处理已移动的星系:

// 替换原主循环中的位移逻辑部分
List<int[]> movimientos = new ArrayList<>();
// 第一步:收集所有需要移动的星系信息
for (int i = 0; i < grid.length; i++) {
    for (int j = 0; j < grid[i].length; j++) {
        for (int k = 0; k < grid[i][j].length; k++) {
            if(grid[i][j][k] != '.'){
                int[] objetivo = encontrarObjetivo(grid, i, j, k);
                if(objetivo != null){
                    movimientos.add(new int[]{i, j, k, objetivo[0], objetivo[1], objetivo[2]});
                }
            }
        }
    }
}
// 第二步:统一执行移动
for(int[] movimiento : movimientos){
    int x = movimiento[0];
    int y = movimiento[1];
    int z = movimiento[2];
    // 防止原位置已被其他星系占用
    if(grid[x][y][z] != '.'){
        int[] objetivo = new int[]{movimiento[3], movimiento[4], movimiento[5]};
        desplazamiento(grid, objetivo, x, y, z);
    }
}

修复后的完整代码

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class galaxias_char {
    public static void main(String... args) throws InterruptedException, IOException {

        int rows = 10;
        int cols = 10;
        int depth = 10;

        char[][][] grid = new char[rows][cols][depth];

        InicializarTablero(grid);

        grid[0][2][2] = '8';
        grid[0][8][7] = '2';

        for(int gen = 1; gen <= 50; gen++){
            new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
            System.out.println("\n--> [Generación " + gen + "]");
            imprimirTablero(grid);

            // 收集所有移动操作
            List<int[]> movimientos = new ArrayList<>();
            for (int i = 0; i < grid.length; i++) {
                for (int j = 0; j < grid[i].length; j++) {
                    for (int k = 0; k < grid[i][j].length; k++) {
                        if(grid[i][j][k] != '.'){
                            int[] objetivo = encontrarObjetivo(grid, i, j, k);
                            if(objetivo != null){
                                movimientos.add(new int[]{i, j, k, objetivo[0], objetivo[1], objetivo[2]});
                            }
                        }
                    }
                }
            }

            // 统一执行移动
            for(int[] movimiento : movimientos){
                int x = movimiento[0];
                int y = movimiento[1];
                int z = movimiento[2];
                if(grid[x][y][z] != '.'){
                    int[] objetivo = new int[]{movimiento[3], movimiento[4], movimiento[5]};
                    desplazamiento(grid, objetivo, x, y, z);
                }
            }

            Thread.sleep(1000);
        }
    }

    public static void InicializarTablero(char[][][] grid) {
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                for (int k = 0; k < grid[i][j].length; k++) {
                    grid[i][j][k] = '.';
                }
            }
        }
    }

    public static void imprimirTablero(char[][][] grid) {
        for (int capa = 0; capa < grid.length; capa++) {
            System.out.println("\n--> {Capa: " + capa + "}");
            for (int fila = 0; fila < grid[capa].length; fila++) {
                for (int columna = 0; columna < grid[capa][fila].length; columna++) {
                    System.out.print(grid[capa][fila][columna] + " ");
                }
                System.out.println();
            }
        }
    }

    public static int[] encontrarObjetivo(char[][][] grid, int x, int y, int z){
        int distanciaMinima = Integer.MAX_VALUE;
        int[] objetivo = null;
        int masaActual = Character.getNumericValue(grid[x][y][z]);
        
        if(masaActual == -1) return null;
        
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                for (int k = 0; k < grid[i][j].length; k++) {
                    int masaObjetivo = Character.getNumericValue(grid[i][j][k]);
                    if(grid[i][j][k] != '.' && masaObjetivo > masaActual){
                        int distancia = Math.abs(x - i) + Math.abs(y - j) + Math.abs(z - k);
                        if(distancia < distanciaMinima){
                            distanciaMinima = distancia;
                            objetivo = new int[]{i, j, k, distancia};
                        }
                    }
                }
            }
        }
        return objetivo;
    }

    public static void desplazamiento(char[][][] grid, int[] objetivo, int x, int y, int z){
        int objX = objetivo[0];
        int objY = objetivo[1];
        int objZ = objetivo[2];
        
        int dirX = Integer.compare(objX, x);
        int dirY = Integer.compare(objY, y);
        int dirZ = Integer.compare(objZ, z);
        
        int newX = x + dirX;
        int newY = y + dirY;
        int newZ = z + dirZ;
        
        if (newX >= 0 && newX < grid.length && 
            newY >= 0 && newY < grid[0].length && 
            newZ >= 0 && newZ < grid[0][0].length &&
            grid[newX][newY][newZ] == '.') {
            grid[newX][newY][newZ] = grid[x][y][z];
            grid[x][y][z] = '.';
        }
    }
}

内容的提问来源于stack exchange,提问作者manznanin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 07:04:55