User Tools

Site Tools


java:2by2rubikcube

The Rubik's cube 2 by 2

Because I'm not good at all at solving this puzzle, I've decided to give Java an opportunity to solve it for me.

So, I've made a program to solve the rubik's cube. If you want to simply run the program, here it is:

rubik.zip

Just uncompress the contents of this zip file and you will find a file called rubik.jar. Run it using the following command:

java -jar rubik.jar

And you the program will start.

Remember that the faces of the cube must be read as if you were reading a text: from left to right, topmost to bottom.

And the source code of the project:

rubik_src.zip

My comments

The data structure I've choose for the cube is in fact a 4×4 matrix of colors:

public class Cube22 implements Cube {
 
	private static final int SIDE_SIZE = 2;
	private static final String nl = System.getProperty("line.separator");
	private Color[][][] cube = new Color[SIDE_SIZE+2][SIDE_SIZE+2][SIDE_SIZE+2];
 
 
	// default constructor: a cube 
	// with all the colors correct
	public Cube22()
	{
	    /*
	     *        TOP OF THE CUBE
	     *  +-+-+-+-+
         *  | | | | |
         *  +-+-+-+-+
         *  | |b|b| |
         *  +-+-+-+-+
         *  | |b|b| |
         *  +-+-+-+-+
         *  | | | | |
         *  +-+-+-+-+
	     */
        cube[0][0][0] = Color.NOCOLOR; cube[1][0][0] = Color.NOCOLOR; cube[2][0][0] = Color.NOCOLOR; cube[3][0][0] = Color.NOCOLOR;
        cube[0][1][0] = Color.NOCOLOR; cube[1][1][0] = Color.BLUE;    cube[2][1][0] = Color.BLUE;    cube[3][1][0] = Color.NOCOLOR;
        cube[0][2][0] = Color.NOCOLOR; cube[1][2][0] = Color.BLUE;    cube[2][2][0] = Color.BLUE;    cube[3][2][0] = Color.NOCOLOR;
        cube[0][3][0] = Color.NOCOLOR; cube[1][3][0] = Color.NOCOLOR; cube[2][3][0] = Color.NOCOLOR; cube[3][3][0] = Color.NOCOLOR;
        /*
         *        VERTICAL COLORS, 1
         *  +-+-+-+-+
         *  | |V|V| |
         *  +-+-+-+-+
         *  |W| | |Y|
         *  +-+-+-+-+
         *  |W| | |Y|
         *  +-+-+-+-+
         *  | |R|R| |
         *  +-+-+-+-+
         */
        cube[0][0][1] = Color.NOCOLOR; cube[1][0][1] = Color.VIOLET;  cube[2][0][1] = Color.VIOLET;  cube[3][0][1] = Color.NOCOLOR;
        cube[0][1][1] = Color.WHITE;   cube[1][1][1] = Color.NOCOLOR; cube[2][1][1] = Color.NOCOLOR; cube[3][1][1] = Color.YELLOW;
        cube[0][2][1] = Color.WHITE;   cube[1][2][1] = Color.NOCOLOR; cube[2][2][1] = Color.NOCOLOR; cube[3][2][1] = Color.YELLOW;
        cube[0][3][1] = Color.NOCOLOR; cube[1][3][1] = Color.RED;     cube[2][3][1] = Color.RED;     cube[3][3][1] = Color.NOCOLOR;
        /*
         *        VERTICAL COLORS, 2
         *  +-+-+-+-+
         *  | |V|V| |
         *  +-+-+-+-+
         *  |W| | |Y|
         *  +-+-+-+-+
         *  |W| | |Y|
         *  +-+-+-+-+
         *  | |R|R| |
         *  +-+-+-+-+
         */
        cube[0][0][2] = Color.NOCOLOR; cube[1][0][2] = Color.VIOLET;  cube[2][0][2] = Color.VIOLET;  cube[3][0][2] = Color.NOCOLOR;
        cube[0][1][2] = Color.WHITE;   cube[1][1][2] = Color.NOCOLOR; cube[2][1][2] = Color.NOCOLOR; cube[3][1][2] = Color.YELLOW;
        cube[0][2][2] = Color.WHITE;   cube[1][2][2] = Color.NOCOLOR; cube[2][2][2] = Color.NOCOLOR; cube[3][2][2] = Color.YELLOW;
        cube[0][3][2] = Color.NOCOLOR; cube[1][3][2] = Color.RED;     cube[2][3][2] = Color.RED;     cube[3][3][2] = Color.NOCOLOR;
        /*
         *        BOTTOM OF THE CUBE
         *  +-+-+-+-+
         *  | | | | |
         *  +-+-+-+-+
         *  | |G|G| |
         *  +-+-+-+-+
         *  | |G|G| |
         *  +-+-+-+-+
         *  | | | | |
         *  +-+-+-+-+
         */
        cube[0][0][3] = Color.NOCOLOR; cube[1][0][3] = Color.NOCOLOR; cube[2][0][3] = Color.NOCOLOR; cube[3][0][3] = Color.NOCOLOR;
        cube[0][1][3] = Color.NOCOLOR; cube[1][1][3] = Color.GREEN;   cube[2][1][3] = Color.GREEN;   cube[3][1][3] = Color.NOCOLOR;
        cube[0][2][3] = Color.NOCOLOR; cube[1][2][3] = Color.GREEN;   cube[2][2][3] = Color.GREEN;   cube[3][2][3] = Color.NOCOLOR;
        cube[0][3][3] = Color.NOCOLOR; cube[1][3][3] = Color.NOCOLOR; cube[2][3][3] = Color.NOCOLOR; cube[3][3][3] = Color.NOCOLOR;
 
	} // Cube22
 
    @Override
    public Color getColor( int x, int y, int z )
    {
        return cube[x][y][z];
    }
    @Override
    public void setColor( int x, int y, int z, Color color )
    {
        cube[x][y][z] = color;
    }
 
    @Override
    public Cube getCopy()
    {
        Cube22 result = new Cube22();
 
        for( int x = 0; x < 4; x++ )
            for( int y = 0; y < 4; y++ )
                for( int z = 0; z < 4; z++ )
                {
                    result.setColor(x, y, z, getColor(x, y, z));
                }
 
        return result;
 
    } // getCopy 
 
	@Override
	public String toString()
	{
	    StringBuilder out = new StringBuilder();
 
	    out.append( "        ____________ " ); out.append( nl );
	    out.append( "       /     /     /|" ); out.append( nl ); 
	    out.append( "      /  "+Color.toString(cube[1][1][0])+"  /   "+Color.toString(cube[2][1][0])+" / |" ); out.append( nl );
	    out.append( "     /_____/_____/ "+Color.toString(cube[3][1][1])+"|" ); out.append( nl );
	    out.append( "    /     /     /|  ," ); out.append( nl );
	    out.append( "   /  "+Color.toString(cube[1][2][0])+"  /   "+Color.toString(cube[2][2][0])+" / | /|" ); out.append( nl );
	    out.append( "  /_____/_____/  |/ |" ); out.append( nl );
	    out.append( "  |     |     |"+Color.toString(cube[3][2][1])+" / "+Color.toString(cube[3][1][2])+"," ); out.append( nl ); 
	    out.append( "  |  "+Color.toString(cube[1][3][1])+"  |  "+Color.toString(cube[2][3][1])+"  | /| / " ); out.append( nl );
	    out.append( "  |_____|_____|/ |/  " ); out.append( nl );
	    out.append( "  |     |     |"+Color.toString(cube[3][2][2])+" /   " ); out.append( nl );
	    out.append( "  |  "+Color.toString(cube[1][3][2])+"  |  "+Color.toString(cube[2][3][2])+"  | /    " ); out.append( nl );
	    out.append( "  |_____|_____|/     " ); out.append( nl );
 
	    return out.toString();
 
	} // toString
 
	/**
	 * Return true if the cube is solved, in other words, all the colors 
	 * are grouped in the same face of the cube.
	 * 
	 * @return
	 */
	@Override
	public boolean isSolved()
	{
        boolean facade1;
        boolean facade2;
        boolean facade3;
        boolean facade4;
        boolean facade5;
        boolean facade6;
 
	    facade1 = cube[1][1][0] == cube[2][1][0] && cube[2][1][0] == cube[1][2][0] && cube[1][2][0] == cube[2][2][0];
        facade2 = cube[3][2][1] == cube[3][1][1] && cube[3][1][1] == cube[3][1][2] && cube[3][1][2] == cube[3][2][2];
        facade3 = cube[1][3][1] == cube[2][3][1] && cube[2][3][1] == cube[1][3][2] && cube[1][3][2] == cube[2][3][2];
        facade4 = cube[1][1][3] == cube[2][1][3] && cube[2][1][3] == cube[1][2][3] && cube[1][2][3] == cube[2][2][3];
        facade5 = cube[0][2][1] == cube[0][1][1] && cube[0][1][1] == cube[0][1][2] && cube[0][1][2] == cube[0][2][2];
        facade6 = cube[1][0][1] == cube[2][0][1] && cube[2][0][1] == cube[1][0][2] && cube[1][0][2] == cube[2][0][2];
 
        return facade1 && facade2 && facade3 && facade4 && facade5 && facade6;
	}
 
 
	/**
	 * Determine if two cubes are equal regardless of their orientation.
	 * This is important because this, applied to the search algorithm
	 * prevents to explore branches that in fact are the seame than a 
	 * previous one but with the colors rotated. 
	 * 
	 */
	@Override
	public boolean equals( Object comp )
	{
	    if( this == comp )
	        return true; 
	    if( comp instanceof Cube22 )
	    {
	        Cube22 compCube = (Cube22) comp; 
	        return equalsXYZ(compCube);
	    }
	    else
	        return false;
	} // equals
 
 
   public boolean equalsXYZ( Cube compCube )
    {
        boolean equal = true; 
        for( int x = 0; x < SIDE_SIZE+2 && equal; x++ )
            for( int y = 0; y < SIDE_SIZE+2 && equal; y++ )
                for( int z = 0; z < SIDE_SIZE+2 && equal; z++ )
                    equal = equal && (cube[x][y][z] == compCube.getColor(x, y, z));
        return equal;
    } // equals
 
}

After two days developing (in my spare time) I've realized that it was a wrong decision, because there is a better way to store the cube and allow the rotation operations to be more easy: is to create a sticker data structure and link the stickers between them. Thus, the operation of rotation of the cube is more easy and less error prone.

An idea of what it would be:

class Sticker
{
   private Sticker north; 
   private Sticker south; 
   private Sticker east;
   private Sticker west; 
   private Sticker northCorner; 
 
}

So, the cube is constructer by linking the respective north, south, east … links between them. But I think it would be needed to keep a link in order to know the orientation of the cube (to know what is up and down): because of this is necessary this northCorner, who will be set with a value only with one sticker.

java/2by2rubikcube.txt · Last modified: 2022/12/02 22:02 by 127.0.0.1