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("--> 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("---> 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
相关产品推荐
相关产品推荐

