I'm working on a JavaFX project where I need to manage a 3D grid representing a Tetris-like game environment. My current implementation involves multiple nested loops and array manipulations, which I suspect might not be the most efficient approach. The code involves generating and placing Tetris-like shapes in a 3D grid, represented by a multi-dimensional array. Below is a snippets of the critical sections of my code:
static int[][] makeSparseMatrix(){
int[][][] empty3DGrid = new int[magic_cols][magic_rows][magic_depth];
ok.add(AOrientations);
ok.add(COrientations);
ok.add(BOrientations);
char[] da_chars = new char[3];
da_chars[0] = 'A';
da_chars[2] = 'B';
da_chars[1] = 'C';
for (int[][][][] ori : ok){
for (int i = 0; i < ori.length; i++) {
for (int col = 0; col < magic_cols; col++){
for (int row = 0; row < magic_rows; row++){
for (int zed = 0; zed < magic_depth; zed++){
empty3DGrid = new int[magic_cols][magic_rows][magic_depth];
//fullpiece is
int[][][] fullpiece = ori[i];
if (isPlacable(empty3DGrid, fullpiece, col, row, zed)){
placeShapeInSpace(empty3DGrid, fullpiece, col, row, zed);
//idk
addRowToRows(empty3DGrid, col,row,zed, da_chars[ok.indexOf(ori)], i);
}
}
}
}
}
}
return theRows.stream().map(u -> u.stream().mapToInt(i -> i).toArray()).toArray(int[][]::new);
}
private static void addRowToRows(int[][][] gridWithPiecePlaced, int x, int y, int z, int pentoChar, int OrietationIndex) {
ArrayList<Integer> positions = new ArrayList<>();
for (int i = 0; i < magic_cols; i++){
for (int j = 0; j < magic_rows; j++){
for (int k = 0; k < magic_depth; k++){
positions.add(gridWithPiecePlaced[i][j][k]);
}
}
}
//Keeps info to find solution after the dlx gives the solution
int[] Pentomino_Position_Information = { pentoChar , x, y, z, OrietationIndex };
PentominoToRow.put(positions, Pentomino_Position_Information);
theRows.add(positions);
}
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
// Your scheduled task code
// For example, fetching or computing game data
// Ensure thread safety if accessing shared data
Platform.runLater(() -> {
// Your UI update code here
System.out.println(getSols());
int[][][] box = new int[HelloApplication.WIDTH][HelloApplication.HEIGHT][HelloApplication.DEPTH];
for (String sol : sols) {
char[] b = sol.toCharArray();
char c = b[0];
int lenString = b.length;
//29 or 30
int x = 0;
int y = 0;
int z = 0;
int rot = 0;
if (lenString == 29){
x = Integer.parseInt(String.valueOf(b[14]));
y = Integer.parseInt(String.valueOf(b[16]));
z = Integer.parseInt(String.valueOf(b[18]));
rot = Integer.parseInt(String.valueOf(b[28]));
} else if (lenString == 30){
x = Integer.parseInt("" + b[14] + b[15]);
y = Integer.parseInt(String.valueOf(b[17]));
z = Integer.parseInt(String.valueOf(b[19]));
rot = Integer.parseInt(String.valueOf(b[29]));
} else {
System.out.println("fuck off");
}
//c and rotation to shape int[][][]
int[][][][] a = getOrientationsInBinaryFormat(c);
int[][][] ggggg = a[rot];
if (isPlacable(box,ggggg,x,y,z)){
placeShapeInSpace(box, ggggg, x, y, z, c);
}
}
HelloApplication.updateVisualsFromField(box);
sols.clear();
});
}, 0, 5000, TimeUnit.MILLISECONDS);
System.out.println("Done field");
}
static void runExample() throws InterruptedException {
new Thread(() -> {
int[][] example = makeSparseMatrix();
DancingLinks DLX = new DancingLinks(example);
try {
DLX.runSolver();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
public static void ReturnPentominoesUsed(ArrayList<String> answers) throws InterruptedException{
// take the possible answers and turn each of them into readable user form
int[][][] field = new int[magic_cols][magic_rows][magic_depth];
for (String curr_answer : answers) {
curr_answer = curr_answer.stripTrailing();
String[] splitArray = curr_answer.split(" ");
ArrayList<Integer> array_list = new ArrayList<>();
for (String s : splitArray) {
array_list.add(Integer.parseInt(s));
}
// Checking the rows now
for (ArrayList<Integer> Row : theRows) {
int index = 0;
for (Integer vlera : array_list) {
if (Row.get(vlera) == 1) {
index++;
}
}
// This means that the Row had all the positions and their possible size
// confirmed
// So we get a unique result.
if (index == array_list.size()) {
int[] pentominoInfo = PentominoToRow.get(Row);
char pentoChar = (char) pentominoInfo[0];
int x = pentominoInfo[1];
int y = pentominoInfo[2];
int z = pentominoInfo[3];
int OrienIndex = pentominoInfo[4];
System.out.println(pentoChar + " at position " + x + " " + y + " " + z + " rotation" + OrienIndex);
sols.add(pentoChar + " at position " + x + " " + y + " " + z + " rotation" + OrienIndex);
//when sols change
// get the piece with all orientations
int[][][][] full_piece_oris = ok.get(pentoChar - 65);
int[][][] full_piece = full_piece_oris[OrienIndex];
// add the piece to show to user
if (isPlacable(field, full_piece, x, y ,z)){
placeShapeInSpace(field, full_piece, x, y ,z);
}
}
}
}
public static void placeShapeInSpace(int[][][] space, int[][][] shape, int startX, int startY, int startZ, char Z) {
int coolint = 0;
if (Z == 'A'){
coolint = 1;
} else if (Z == 'B'){
coolint = 2;
} else if (Z == 'C'){
coolint = 3;
}
for (int x = 0; x < shape.length; x++) {
for (int y = 0; y < shape[0].length; y++) {
for (int z = 0; z < shape[0][0].length; z++) {
// Check if the current point in the shape is part of the structure (i.e., it's a 1)
if (shape[x][y][z] == 1) {
// Calculate the corresponding indices in the space
int spaceX = startX + x;
int spaceY = startY + y;
int spaceZ = startZ + z;
// Check that the indices are within the bounds of the space
if (spaceX >= 0 && spaceX < space.length &&
spaceY >= 0 && spaceY < space[0].length &&
spaceZ >= 0 && spaceZ < space[0][0].length) {
// Place the part of the shape into the space
space[spaceX][spaceY][spaceZ] = coolint;
}
}
}
}
}
}
public static boolean isPlacable(int[][][] space, int[][][] shape, int startX, int startY, int startZ) {
// Iterate over each dimension of the shape
for (int x = 0; x < shape.length; x++) { // shape.length should be 2 for X dimension
for (int y = 0; y < shape[0].length; y++) { // shape[0].length should be 2 for Y dimension
for (int z = 0; z < shape[0][0].length; z++) { // shape[0][0].length should be 4 for Z dimension
// Check if the current point in the shape is part of the structure (i.e., it's a 1)
if (shape[x][y][z] == 1) {
// Calculate the corresponding indices in the space
int spaceX = startX + x;
int spaceY = startY + y;
int spaceZ = startZ + z;
// Check that the indices are within the bounds of the space
if (spaceX < 0 || spaceX >= space.length ||
spaceY < 0 || spaceY >= space[0].length ||
spaceZ < 0 || spaceZ >= space[0][0].length) {
return false; // Out of bounds
}
// Check if the space is already occupied
if (space[spaceX][spaceY][spaceZ] != 0) {
return false; // Cannot place as the space is occupied
}
}
}
}
}
return true; // Shape can be placed
}
I tried some pruning aproaches but ive ran out of ideas. It doesent seem to work for rooms like 9x9x9. it does solve 6x6x6 pretty quick though. My final objective is to check all the possibilities for a big room of approximately 33, 8, 5 dimenstions given like 3 boxes of different dimensions to put inside it with no limit per box. I am using basic DLX code i just make the matrix and pass it by it.