Reputation: 49
I've got a representation of a Rubik's Cube and I'm trying to add rotation methods. I've been banging my head against this for more than a day, and I just can't find the bug in my code.
I've got a Box class which has string attributes for each of its six faces. I fill a 3X3X3 array with Boxes in the Cube class (including a redundant Box at the center of the Cube, but this code is still unoptimized). Then I assign the correct colors to the boxes, with values of 'none' if that face isn't visible from outside the Cube.
Up until here, it works perfectly, but when I added the first rotation method, rot_front(), it spits out a weird result.
I've added debug methods if you wanna try it out. Here's my code:
class Box:
def __init__(self):
self.top = 'none'
self.bottom = 'none'
self.right = 'none'
self.left = 'none'
self.front = 'none'
self.back = 'none'
class Cube:
def __init__(self):
self.boxes = [[[Box() for i in range(3)] for i in range(3)] for i in range(3)]
for z in range(3):
for y in range(3):
for x in range(3):
if z == 0:
self.boxes[z][y][x].front = 'white'
if z == 2:
self.boxes[z][y][x].back = 'yellow'
if y == 0:
self.boxes[z][y][x].top = 'red'
if y == 2:
self.boxes[z][y][x].bottom = 'orange'
if x == 0:
self.boxes[z][y][x].left = 'blue'
if x == 2:
self.boxes[z][y][x].right = 'green'
def print_front(self):
z = 0
for y in range(3):
for x in range(3):
print(cube.boxes[z][y][x].front, end=" ")
print("")
def print_back(self):
z = 2
for y in range(3):
for x in range(3):
print(cube.boxes[z][y][x].back, end=" ")
print("")
def print_top(self):
y = 0
for z in range(3):
for x in range(3):
print(cube.boxes[z][y][x].top, end=" ")
print("")
def print_bottom(self):
y = 2
for z in range(3):
for x in range(3):
print(cube.boxes[z][y][x].bottom, end=" ")
print("")
def print_left(self):
x = 0
for z in range(3):
for y in range(3):
print(cube.boxes[z][y][x].left, end=" ")
print("")
def print_right(self):
x = 2
for z in range(3):
for y in range(3):
print(cube.boxes[z][y][x].right, end=" ")
print("")
def rot_front(self):
front_face = self.boxes[0]
for y in range(3):
for x in range(3):
target = front_face[2-x][y]
self.boxes[0][y][x].top = target.left
self.boxes[0][y][x].right = target.top
self.boxes[0][y][x].bottom = target.right
self.boxes[0][y][x].left = target.bottom
cube = Cube()
cube.rot_front()
print("FRONT")
cube.print_front()
print("BACK")
cube.print_back()
print("TOP")
cube.print_top()
print("BOTTOM")
cube.print_bottom()
print("LEFT")
cube.print_left()
print("RIGHT")
cube.print_right()
Thanks in advance for your help!
Upvotes: 0
Views: 1043
Reputation: 1599
The easiest method is to make a deepcopy of self.boxes
and change it and then replace self.boxes
at the end of the rotation:
import copy
class Cube:
# other methods stay the same
def rot_front(self):
front_face = self.boxes[0]
new_state = copy.deepcopy(self.boxes)
for y in range(3):
for x in range(3):
target = front_face[2-x][y]
new_state[0][y][x].top = target.left
new_state[0][y][x].right = target.top
new_state[0][y][x].bottom = target.right
new_state[0][y][x].left = target.bottom
self.boxes = new_state
The mistake you made is a little bit hard to explain because I'm not a native english speaker, bit I'll try:
You are moving the information from one box to another in the loop. But in some cases the information in target
contains information which already was moved and you move it again.
Upvotes: 2