0

I am trying to simulate Rubik's Cube. In order to detect if user has actually solved the Cube I would like to remember all initial position vectors and then just compare it.

However, when you start my program and mess the cube, then press 'k' to solve it you can see in the console that values in fact are the same, however they have different precision. For example z-value is -0.99999 instead of -1. The result of this flaw is that even though the values are quite the same, the program still won't consider the Cube solved. I guess that while rotating, when calculations are performed on the vector, the precision changes and as a result in the end the values are different. How can I solve this problem? To print out the initial position vectors and current vectors press 'a' key anytime you wish to :)

from visual import *
import string
import random

class Cube:
    def __init__(self):
        self.surfaces = { 'r': (color.red, (1, 0, 0)), 
                              'o': (color.orange, (-1, 0, 0)),
                              'y': (color.yellow, (0, 1, 0)), 
                              'b': (color.blue, (0, -1, 0)),
                              'w': (color.white, (0, 0, 1)), 
                              'g': (color.green, (0, 0, -1))} 
        self.fps = 30
        self.wholeSurfaces = []
        self.initialPosition = []
        self.commandsList = []

    def createCube(self):
         for colour, axis in self.surfaces.itervalues():
            for x in (-1, 0, 1):
                for y in (-1, 0, 1):

                    # Start with all powierzchniaBoczna on the top face, then rotate them "down"
                    # to the appropriate face.
                    powBoczna = box(color=colour, pos=(x, y, 1.5),
                                  length=0.98, height=0.98, width=0.05)

                    cos_kat = dot((0, 0, 1), axis)

                    if cos_kat == 0: #alfa = 90 + kPI
                        obliczonaOsObrotu = cross((0, 0, 1), axis) #iloczyn wektorowy
                    else: 
                        obliczonaOsObrotu=(1, 0, 0)

                    powBoczna.rotate(angle=acos(cos_kat), axis=obliczonaOsObrotu, origin=(0, 0, 0))
                    self.wholeSurfaces.append(powBoczna)

                    #remember initial position
                    v = (float(powBoczna.pos.x), float(powBoczna.pos.y), float(powBoczna.pos.z))
                    self.initialPosition.append(v)

    def solveCube(self):
        print self.commandsList

        self.commandsList.reverse()

        print self.commandsList
        for i in self.commandsList:
            self.rotateCube(self.reverseCommand(i), 10000)
        self.commandsList = []

    def reverseCommand(self, key):
        if (key.islower()): return key.upper()
        else: return key.lower()

    def rotateCube(self, key, refreshRate):
                colour, axis = self.surfaces[key.lower()]

                if (key.isupper()): kat = (pi / 2.0) 
                else: kat = -pi/2.0


                for r in arange(0, kat, kat / self.fps):
                    rate(refreshRate) 

                    for surface in self.wholeSurfaces:
                        if dot(surface.pos, axis) > 0.5: 
                            surface.rotate(angle=kat / self.fps, axis=axis, origin=(0, 0, 0))

    def beginLoop(self):       
        while True:
            key = scene.kb.getkey() 
            if (key.lower() in self.surfaces):
                self.commandsList.append(key)
                self.rotateCube(key, self.fps)
            elif key == "k":
                self.solveCube()
            elif key == "a":
                i = 0
                print "================="
                for surface in self.wholeSurfaces:
                        print "%s\n(%s,%s,%s)" % (self.initialPosition[i], surface.pos.x, surface.pos.y, surface.pos.z)
                        if self.initialPosition[i][0] == float(surface.pos.x) and self.initialPosition[i][1] == float(surface.pos.y) and self.initialPosition[i][2] == float(surface.pos.z): print "equal"
                        else: print "not equal"
                        print ""
                        i+=1

if __name__ == "__main__":
    myCube = Cube()
    myCube.createCube()
    myCube.beginLoop()
Zwierzak
  • 666
  • 1
  • 11
  • 31

1 Answers1

0

The solution is simple, you need to use numpy.allclose method with given precision.

for surface in self.wholeSurfaces:
    print "%s\n%s" % (self.initialPosition[i], powierzchnia.pos)
    if np.allclose(self.initialPosition[i], surface.pos.astuple(), 1e-5, 1e-5): print "are equal"
    else: print "arent equal"
    i+=1
Zwierzak
  • 666
  • 1
  • 11
  • 31