Search code examples
javamultidimensional-arrayrubiks-cube

Copying parts of a multidimensional array


I'm trying to create a Rubiks cube using 6, 2D arrays for each face of the cube. I'm able to spin the entire cube using this code but for some reason when I try and "turn" one vertical strip of the cube it does not work properly. Here is what I have so far

import java.util.*;
public class RubiksCube {
    public static void main(String[] args) {
        String Empty[][] = {{"0","0","0"},{"0","0","0"},{"0","0","0"}};
        String Front[][] = {{"F1","F1","F1"},{"F2","F2","F2"},{"F3","F3","F3"}};
        String Back [][] = {{"B1","B1","B1"},{"B2","B2","B2"},{"B3","B3","B3"}};
        String Top  [][] = {{"T1","T1","T1"},{"T2","T2","T2"},{"T3","T3","T3"}};
        String Under[][] = {{"U1","U1","U1"},{"U2","U2","U2"},{"U3","U3","U3"}};
        String Left [][] = {{"L1","L1","L1"},{"L2","L2","L2"},{"L3","L3","L3"}};
        String Right[][] = {{"R1","R1","R1"},{"R2","R2","R2"},{"R3","R3","R3"}};

        Scanner Scan = new Scanner(System.in);
        boolean repeat = true;

        while (repeat) {
            for (int x = 0; x < Front.length; x++) {
                for (int y = 0; y < Front[0].length; y++) {
                    System.out.print(Under[x][y]);
                }
                System.out.println();
             }

            String command = Scan.nextLine();
            Empty = Back;

            if (command.equalsIgnoreCase("Up")) {
                Back  = Top;
                Top   = Front;
                Front = Under;
                Under = Empty;
            }

            if (command.equalsIgnoreCase("up1")) {
                for (int x = 0; x < 3; x++) {
                    Back [x][0] = Top  [x][0];
                    Top  [x][0] = Front[x][0];
                    Front[x][0] = Under[x][0];  
                    Under[x][0] = Empty[x][0];
               }
            }
        }
    }
}

So if this cube is being flipped up then the bottom of the cube become the front, the back becomes the bottom, etc. When I do this using the "Up1" command however the bottom of the cube seems to disappear from my arrays and the top gets doubled into two of the arrays. What am I doing wrong? I'm very new to using multidimensional arrays so am I making some silly mistake?

Edit: So to simplify things for some reason this works

if (command.equalsIgnoreCase("up1")) {
     String[] tmp = { Back[0][0], Back[1][0], Back[2][0] };
        for (int x=0;x<3;x++) {
          Back[x][0] = Top[x][0];
          Top[x][0] = Front[x][0];
          Front[x][0] = Under[x][0];    
          Under[x][0] = tmp[x];
        }
    }

But this does not

 if (command.equalsIgnoreCase("up1")) {
     String tmp [][] = Back;
        for (int x=0;x<3;x++) {
          Back[x][0] = Top[x][0];
          Top[x][0] = Front[x][0];
          Front[x][0] = Under[x][0];    
          Under[x][0] = tmp[x][0];
        }
    }

Why does the second version not work correctly?

Edit2:

Example with code that works correctly. It cycles through the under, bottom, top, front, and then under again

U1 U1 U1    
U2 U2 U2    
U3 U3 U3

Input: up1

B1 U1 U1    
B2 U2 U2    
B3 U3 U3    

Input: up1

T1 U1 U1    
T2 U2 U2    
T3 U3 U3    

Input: up1

F1 U1 U1    
F2 U2 U2    
F3 U3 U3

Input: up1

U1 U1 U1    
U2 U2 U2    
U3 U3 U3    

Example with the code that uses a 2D temporary array that does not work properly. It skips the bottom of the cube for some reason

U1 U1 U1    
U2 U2 U2    
U3 U3 U3   

Input: up1

T1 U1 U1    
T2 U2 U2    
T3 U3 U3    

Input: up1

F1 U1 U1    
F2 U2 U2    
F3 U3 U3 

Input up1

U1 U1 U1    
U2 U2 U2    
U3 U3 U3

Input: up1

T1 U1 U1    
T2 U2 U2    
T3 U3 U3

Solution

  • I believe a more correct (but still incomplete) logic would rather be:

     String[] tmp = { Back[0][0], Back[1][0], Back[2][0] };
    
     // this logic only takes into account the changes that occur             
     for (int i = 0; i < 3; i++) {
         Back [i][0] = Under[i][0];
         Under[i][0] = Front[i][0];
         Front[i][0] = Top  [i][0];
         Top  [i][0] = tmp  [i];
     }
    

    You need to use a temporary array that stores the values of the first block that you are about to move to record its value before you start overwriting it and re-use it at the end of the rotation to update the last block with the previous values of the first block.

    Also, the order of the blocks to move in your english sentence did not match with your code, so I corrected this as well. Finally, I don't think only moving the first value of each block will be enough. I can't really propose a complete solution because I don't know in which order you decided to index the arrays. For example, is Back[0][0] at the top-left or at the top-right ? I could see arguments for both decisions.

    Tip: to optimize a little bit and avoid re-allocating a temporary array every time you can allocate a single array of three elements at the start and then always re-use the same during swapping.

    Edit:

    Your second version doesn't work because you're not copying the array, you're just obtaining a reference to the array, which means that if the array is modified your tmp variable is also affected since tmp and Back are two pointers to exactly the same array.