2012-04-29 20 views
8

Quiero aleatorizar un cubo de rubik que se inicializa como completo (todos los colores en los lados correctos). Tengo funciones de movimiento que rotan el cubo. Quiero seleccionar aleatoriamente 50 funciones seguidas para aleatorizarlas adecuadamente.Usar diccionarios en Python en lugar de la sentencia Case/Switch

Estoy haciendo este proyecto para aprender un poco más sobre Python, ya que la mayoría de las veces hago C++ y veo que no hay ningún caso/interruptor para Python, entonces estoy intentando un diccionario. Cuando hago el diccionario, el código parece ejecutar por alguna razón:

def random_cube(self): 
    scramble = { 0 : self.up_turn(), 
        1 : self.down_turn(), 
        2 : self.left_turn(), 
        3 : self.right_turn(), 
        4 : self.front_turn(), 
        5 : self.back_turn(), 
        6 : self.up_turn("inverted"), 
        7 : self.down_turn("inverted"), 
        8 : self.left_turn("inverted"), 
        9 : self.right_turn("inverted"), 
        10: self.front_turn("inverted"), 
        11: self.back_turn("inverted") 
       } 
    for x in range(50): 
     i = random.randint(0,11) 
     scramble[i] 

Así que cuando hago este diccionario, parece correr a través y ejecutar todas las 11 entradas por alguna razón (creo). Parece que no puedo encontrar una manera mejor, al menos más elegante que una larga cadena de declaraciones if/elif.

! EDIT: Implementando ambas sugerencias, el indicador ("invertido") para las funciones no se establece por ninguna sugerencia. Por ejemplo, las llamadas 1 y 7 me dan un down_turn, pero el resultado muestra que el indicador no se configuró cuando debería haber estado en el número 7.

¿Alguna idea?

+1

Como nota al diseño, en realidad sólo hay dos movimiento diferente s uno puede hacerlo en un cubo de rubik.El resto es solo una cuestión de cómo uno orienta las caras. Puede ser más fácil escribir una función así: 'def rotate (face, clockWise = True):' También como alternativa al uso de un dict y 'for' loop, podrías hacer una lista y usar' random.choice' para seleccionar de ella –

+0

para random.choice de la lista, también lo hice con eso. Puse las llamadas de función en una lista y lo intenté, pero no funcionó para mí ... También configuré el cubo para que siempre se viera de color blanco como 'frontal'. No creo que esa sea la mejor manera de representarlo: \ –

Respuesta

15

Cuando define el dict, en realidad está llamando a las funciones y almacenando el valor de retorno en el diccionario. Para que la tienda del diccionario haga referencia a las funciones, debe colocar los paréntesis finales. Así que algo así como:

scramble = { 0: self.up_turn, 
       1: self.down_turn, 
       etc. 

Luego, en la parte inferior, llame al scramble[i]().

Esto llamará a la función sin argumentos. Para manejar el caso donde pasa "invertido" como argumento, puede definir funciones separadas como up_turn_inverted(), etc., o puede tener el diccionario almacenar un 2-ple que consiste en la función, y el argumento, luego llamar algo le gusta scramble[i][0](scramble[i][1])

Actualización de la sugerencia en los comentarios: También podría usar expresiones lambda para definir las funciones, particularmente las que requieren un argumento. Esto es básicamente equivalente a definir una función up_turn_inverted, pero se realiza in situ como una función anónima. Se vería así:

6: lambda: self.up_turn("inverted") 
7: lambda: self.down_turn("inverted") 

etc.

+3

Otra opción sería usar 'lambda:' para crear las llamadas invertidas. – Amber

+0

¿O qué tal un condicional en línea? es decir 'scramble [i] (() if i <6 else (" inverted "))' –

+1

Como principio general, hacer suposiciones sobre el orden del diccionario parece algo que debería evitarse si es posible. Yo votaría por la solución lambda. – happydave

2

Creo que esto se llama "funciona como valores de primera clase", lo que implica que es más importante que usted puede pasar identificadores se refieren a funciones como parámetros a otras funciones.

Cuando define su diccionario, el intérprete de Python evalúa las funciones y almacena los valores en el diccionario. Para dejar esto de lado hasta que generar sus números al azar, en lugar tratar almacenar referencias a las mismas funciones en su diccionario, al dejar fuera de los paréntesis:

def random_cube(self): 
    scramble = { 0 : self.up_turn, 
        1 : self.down_turn, 
        2 : self.left_turn, 
        3 : self.right_turn, 
        4 : self.front_turn, 
        5 : self.back_turn, 
        6 : self.up_turn, 
        7 : self.down_turn, 
        8 : self.left_turn, 
        9 : self.right_turn, 
        10: self.front_turn, 
        11: self.back_turn 
       } 

A continuación, cuando se llama a sus funciones en el bucle for que tendrá que distinguir entre los casos normales e invertidos por el cual se pasa parámetros:

for x in range(50): 
     i = random.randint(0,11) 
     if i <= 5: 
      scramble[i]() 
     else: 
      scramble[i]("inverted") 

o más simplemente:

for x in range(50): 
     i = random.randint(0,11) 
     scramble[i](() if i < 6 else ("inverted")) 
+0

gracias por la respuesta. No estaba pensando en que el intérprete tenga que evaluar para ponerlo en el valor del diccionario. –

Cuestiones relacionadas