Rotate Rubik's Cube array;

Oct 9, 2016 at 7:53pm
Hi all. I'm writing a Rubik's cube program, and would to know of any simple way to rotate the top or bottom of the cube. I have the straight rows and columns rotating correctly, already.
int Rubik_Cube[6][9];
Rubik_Cube[0 thru 5][9] represents each of the 6 sides, while int Rubik_Cube[6][0 thru 8] represents each of the nine cubes on each of the 6 sides

Thanks for any help.

PS.. This is NOT homework. I program for fun, and am 66 years old
Oct 10, 2016 at 4:22am
I don't understand how this representation is supposed to work. How can you only have 9 ints to represent all 9 squares for all 6 sides?
Oct 10, 2016 at 4:32am
@TinyTertle

I don't have only 9 ints. I created a 2D array. Rubik_Cube[6][9]. So, Rubik_Cube[0][ 0 thru 8],
Rubik_Cube[1][ 0 thru 8], Rubik_Cube[2][ 0 thru 8], and so on. Rubik_Cube[0] would be the top, with the 9 afterwards, keeping track of what color is in each top square. Rubik_Cube[1], is the left side, with those 9 in the array, registering those colors. Same for the others, keeping track of each side.
Last edited on Oct 10, 2016 at 4:45am
Oct 10, 2016 at 4:48am
@whitenite1
How amazing... You are already 66 years old...
I think you should not be actually announcing your actual age in public.
Oct 10, 2016 at 5:04am
@SakurasouBusters

I think you should not be actually announcing your actual age in public.


Maybe not, but that doesn't give too much away concerning identity. I could have been born anywhere from 1949 to 1950. I figured I'd put that out in the message, so that anyone reading it, would know I'm NOT in school.

I can probably figure out some code to rotate the ends, but was hoping for a short, elegant way.
Oct 10, 2016 at 5:55pm
Rubik_Cube[0 thru 5][9] represents each of the 6 sides, while int Rubik_Cube[6][0 thru 8] represents each of the nine cubes on each of the 6 sides


First of all, I think you need to tighten up your terminology. A side does not have 9 cubes. A side has 9 squares or faces or colors. If you want to treat the puzzle as 27 cubes that move around, you can do that, but I think you are actually treating this as 6 3x3 grids that are interconnected. So, be careful using the term "cube".

Other things to think about. If you never move a middle band (only move top, bottom, or a side) the middle squares never move. They can rotate (which is not important in a traditional Rubik's cube), but the color never changes.

How you rotate the bottom and top depends on how you have numbered your grids. Assuming all side grids are numbered 0, 1, 2 on the top row, rotating the top counterclockwise would be:

F[0] = old L[0], F[1] = old L[1], F[2] = old L[2], L[0..2] = old B[0..2], B[0..2] = old R[0..2] R[0..2] = old F[0..2]. (B is Back, not Bottom in this example.)

T[0] = old T[2], T[1] = old T[5], T[2] = old T[8], T[3] = old T[1], T[4] = old T[4] (center square does not move), T[5] = old T[7], T[6] = old T[0], T[7] = old T[3] and T[8] = old T[6].

You might be able to do some sort of matrix manipulation to use less code than this, but you won't get much performance improvement over a simplistic brute force method.

If you can figure out a standard orientation of your faces you can write a singe function to rotate any face. By standard orientation, I mean, all faces are oriented with 0 in the upper LH corner and are 0, 1, 2 across the top and the square on the face above the '0' square is the same number for all faces and the squared on the face to the left of the '0' square is the same for all faces. If the orientation of each face vis a vis the orientation of all adjacent faces is the same for all faces on the cube, your coding become much easier.
Oct 10, 2016 at 7:22pm
@doug4

Yeah, I'll have to use the correct terminology, though I know what I mean when I write it.

Here's my screen layout to display each side of the cube ( along with the 9 faces, colors
etc. ;) )
1
2
3
4
5
6
7
8
9
10
11
              012 \
              345   Rubik_Cube[0][0 thru 8]
              678 /

         012  012  012  012 \
         345  345  345  345   Rubik_Cube[1 thru 4][0 thru 8]
         678  678  678  678

              012 \
              345    Rubik_Cube[5][0 thru 8]
              678 /

I already have the columns to to back and forward, the rows to go left and right. So I know how to assign row color to new row colors. I was hoping for an algorithm to make rotating top, bottom and sides(when needed). So, I guess I'll have to go the long route in programming it.

Thanks for your help though.
Last edited on Oct 10, 2016 at 7:24pm
Oct 10, 2016 at 10:11pm
I thought about this some more after I responded. Try this configuration

Face - Name
-----
0 - Front
1 - Top
2 - Right
3 - Bottom
4 - Back
5 - Left


Below, "oriented toward" means the face over the edge from the "0 1 2" row


Positions
=========


Front (with the top row on top)
---------------------------------
(Face 0 - oriented toward Top [1])
0 1 2
3 4 5
6 7 8

Top (with the top row towards the back)
---------------------------------------------------
(Face 1 - oriented toward Right [2])
6 3 0
7 4 1
8 5 2


Right (with the top row on the top)
--------------------------------------------
(Face 2 oriented toward front [0])
0 1 2
3 4 5
6 7 8


Bottom (with the top row facing the front)
-----------------------------------------------------
(Face 3 oriented toward back [4])
8 7 6
5 4 3
2 1 0

Back (with top row facing Bottom)
-------------------------------------------
(Face 4 oriented toward left [5])
2 5 8
1 4 7
0 3 6


Left (with top on the top)
---------------------------------
(Face 5 oriented toward bottom [3])
6 3 0
7 4 1
8 5 2


When you look at any face "f" and orient it so that the 0 1 2 row is on top, you can determine the following:

ff is floor(f/3) (or simply integer division f / 3)

the face "above"is (ff * 3) + (f + 1) % 3
The face top the right is (ff * 3) + (f + 2) % 3
The face to the left is ((ff + 1) % 2) * 3) + ((5 - f) % 3)
The face "below" is ((ff + 1) % 2) * 3) + ((6 - f) % 3)

You only need to write 1 rotate function (or 3 functions: cw, ccw and 2 rotates). Have the function determine the 4 adjacent faces and do a rotate.


Oct 11, 2016 at 2:57pm
@Doug4

Thanks for your updated response, but I think I've come up with a simpler solution.
Actually, I got the idea from your response when I noticed the two different positions the faces could be in. ( Not counting the bottom positions. )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int rotate[2][9] = { { 2, 5, 8, 1, 4, 7, 0, 3, 6 } , { 6, 3, 0, 7, 4, 1, 8, 5, 2 }};
// Above are the locations of the Rubik_Cube array after rotating left or right;
//  012 \
//  345   Starting positions
//  678 /
int moving[9];

for (x = 0; x < 9; x++)
 moving[x] = Rubik_Cube[?][x];
// Get current color values in each of the 9 faces on the side to be rotated.
// The ? is just a place holder. The actual # side is used in the actual code 

// code here to move rows or columns left, right, back or forward, as needed.

// Now put new color face values in  Rubik_Cube array
for (x = 0; x < 9; x++)
 Rubik_Cube[?][rotate[?][x]] = moving[x];


So far, this seems to be working except for Rubik_Cube[0][]. I'll have to check my code later, to see where the problem is.
Oct 11, 2016 at 4:57pm
Yes, simpler is better. I agree. I just don't see the solution you need in your latest response.

I guess I'm missing something. When you rotate a face, you also rotate the ring of squares around the face. If the ring never rotates, you can't change the colors on any of the faces of the puzzle. So, every rotation moves 21 colors (actually 20 because the center color on the face doesn't move). I don't see the movement of the 12 edge colors in your code.

The purpose behind my design is to define what moves when a face is rotated. By defining the faces as I did, you can take any face and orient it 0-2 on the top, and the orientation of adjacent faces will always be the same. So, all you have to do is determine which face is rotating and your function can make sure that all 20 colors move correctly.

It's a complicated design, but it's a complicated problem.

I think your design is as follows (but I'm not sure--correct me if I'm wrong): Front, Right, Left and Back are all oriented with 0-2 on the top. The Top is oriented with 0-2 adjacent to the back. The bottom is oriented with 0-2 adjacent to the front.

If you rotate any of the vertical faces, you will rotate squares 258 from the adjacent-left face and 036 from the adjacent right face. The front will rotate 678 from the top and 012 from the bottom, but the right face will rotate 258 from the top and 258 from the bottom. You need to have 6 different rotate functions, one for each face, to make sure the ring colors are rotated correctly.
Oct 11, 2016 at 5:39pm
@Doug4

I left out the coding where I rotate the rows or columns.
Actually, all my cube fronts are orientated the same. It's how I deal with each, that's different. When I rotate, let's say, row 1, which is cube[0][0] to the back, I rotate cube[3][2] since that is the one which would touch the cube, if wrapped around to the rear
1
2
3
4
5
6
7
8
9
10
// Above are the locations of the Rubik_Cube array after rotating left or right;
//   |- Start using row 1
//  V
//  012 \  < - Row 4
//  345    < - Row 5 - Rubik_Cube[0][] - top 
//  678 / < - Row 6

//  012 \  < - Row 7
//  345    < - Row 8 (Rubik_Cube[2 thru 4][]) 
//  678 / < - Row 9 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
void Shift_Back(int Rubik_Cube[6][9], int row)
{
	int x, y, temp;
	int holder[3] = { 0 };
	int rotate[2][9] = { { 2, 5, 8, 1, 4, 7, 0, 3, 6 }, { 6, 3, 0, 7, 4, 1, 8, 5, 2 } }; // Left - Right
	int moving[9];
	switch (row)
	{
	case 1:
		y = 2;
		for (temp = 0; temp < 3; temp ++)
			holder[temp] = Rubik_Cube[0][temp*3];

		for (x = 0; x < 7; x += 3)
		{
			Rubik_Cube[0][x] = Rubik_Cube[2][x];
			Rubik_Cube[2][x] = Rubik_Cube[5][x];
			Rubik_Cube[5][x] = Rubik_Cube[4][y];
			y += 3;
		}
		for (temp = 0; temp < 3; temp ++)
			Rubik_Cube[4][2+(temp*3)] = holder[temp];
		for (x = 0; x < 9; x++)
			moving[x] = Rubik_Cube[1][x];
		for (x = 0; x < 9; x++)
			Rubik_Cube[1][rotate[1][x]] = moving[x];
		break;
	case 2:
		for (temp = 0; temp < 3; temp++)
			holder[temp]=Rubik_Cube[0][1 + (temp * 3)];

		for (x = 1; x < 8; x += 3)
		{
			Rubik_Cube[0][x] = Rubik_Cube[2][x];
			Rubik_Cube[2][x] = Rubik_Cube[5][x];
			Rubik_Cube[5][x] = Rubik_Cube[4][x];
		}
		for (temp = 0; temp < 3; temp ++)
			Rubik_Cube[4][1+(temp*3)] = holder[temp];
		break;
	case 3:
		y = 0;
		for (temp = 0; temp < 3; temp ++)
			holder[temp] = Rubik_Cube[0][2+(temp *3)];

		for (x = 2; x < 9; x += 3)
		{
			Rubik_Cube[0][x] = Rubik_Cube[2][x];
			Rubik_Cube[2][x] = Rubik_Cube[5][x];
			Rubik_Cube[5][x] = Rubik_Cube[4][y];
			y += 3;
		}
		for (temp = 0; temp < 3; temp ++)
			Rubik_Cube[4][temp*3] = holder[temp];
		for (x = 0; x < 9; x++)
			moving[x] = Rubik_Cube[3][x];
		for (x = 0; x < 9; x++) // Rotates opposite direction, so use rotate[0][x], instead
			Rubik_Cube[3][rotate[0][x]] = moving[x];
	}
}


Yes, it does get a bit complicated, but it's easier for me to visualize in my mind, the cube in 3D.

You need to have 6 different rotate functions

Not really. I just have the two, mixed into one 2D array. I just rotate a full side clockwise, or counter-clockwise, depending on which direction the adjoining face is turning.

If you would like to see the coding I have up to this point, let me know, and I'll put it into my dropbox, for you to download.

Oct 11, 2016 at 7:23pm
I don't need to see it. If you have it figured out, that's all you need.

I think I will play with it myself -- it's something I've wanted to do for years and never got around to. A great lunchtime exercise for the next couple of weeks.

Topic archived. No new replies allowed.