Ir al contenido principal

16.7. La clase JuegoDeLaMona

hora podemos poner nuestra atención en el juego en sí mismo. JuegoDeLaMona es una subclase de JuegoDeCartas con un metodo nuevo denominado jugar que toma una lista de jugadores como parámetro.

Como el metodo __init__ se hereda de JuegoDeCartas, el nuevo objeto JuegoDeLaMona contiene un mazo recientemente mezclado:

   1: Aclass JuegoDeLaMona(JuegoDeCartas):
   2:     def jugar(self, nombres):
   3:         # quitamos la Reina de Treboles
   4:         self.mazo.eliminaCarta(Carta(0,12))
   5:         # construimos una mano para cada jugador
   6:         self.manos = []
   7:         for nombre in nombres :
   8:             self.manos.append(ManoDeLaMona(nombre))
   9:             # repartimos los naipes
  10:             self.mazo.repartir(self.manos)
  11:             print "----- Se han repartido las cartas."
  12:         self.muestraManos()
  13:         # eliminamos las coincidencias iniciales
  14:         emparejadas = self.eliminaTodasLasCoincidencias()
  15:         print "----- Coincidencias eliminadas, el juego comienza."
  16:         self.muestraManos()
  17:         # se juega hasta que se han descartado las 50 cartas
  18:         turno = 0
  19:         cantManos = len(self.manos)
  20:         while emparejadas < 25:
  21:             emparejadas = emparejadas + self.jugarUnTurno(turno)
  22:             turno = (turno + 1) % cantManos
  23:         print "----- El juego termino."
  24:         self.muestraManos()

Algunos de los pasos que componen el juego se han colocado en métodos separados. eliminaTodasLasCoincidencias recorre la lista de manos y llama a eliminaCoincidencias para cada una de ellas:



   1: class JuegoDeLaMona(JuegoDeCartas):
   2:     ...
   3:     def eliminaTodasLasCoincidencias(self):
   4:         cant = 0
   5:         for mano in self.manos:
   6:             cant = cant + mano.eliminaCoincidencias()
   7:         return cant

Como ejercicio, escriba muestraManos, el cual recorre self.manos y muestra cada mano.

 

cant es un acumulador que va sumando la cantidad de concordancias en cada mano y devuelve el total.


Cuando la cantidad total de coincidencias alcanza a las veinticinco significa que se han eliminado cincuenta cartas de las manos, lo que es lo mismo que decir que solo queda una carta y el juego ha terminado.


La variable turno recuerda el turno de cual jugador se esta jugando. Comienza en cero y se incrementa en uno cada vez; cuando alcanza el valor cantManos, el operador de modulo lo hace volver a cero.


El metodo jugarUnTurno toma un parámetro que indica de quien es el turno. El valor de retorno es la cantidad de concordancias que se han realizado durante ese turno:




   1: class JuegoDeLaMona(JuegoDeCartas):
   2: ...
   3:     def jugarUnTurno(self, i):
   4:         if self.manos[i].estaVacio():
   5:             return 0
   6:         vecino = self.encuentraVecino(i)
   7:         cartaElegida = self.manos[vecino].darCarta()
   8:         self.manos[i].agregaCarta(cartaElegida)
   9:         print "Mano", self.manos[i].nombre, "eligi¶o", cartaElegida
  10:         cant = self.manos[i].eliminaCoincidencias()
  11:         self.manos[i].mezclar()
  12:         return cant

Si la mano de un jugador esta vacía, el jugador salió del juego, así que no hace nada y devuelve 0.


Si no, un turno consiste en encontrar el primer jugador a la izquierda que aun tiene cartas, tomar una carta de las que posee, y controlar si hay concordancias.


Antes de volver se mezclan las cartas de la mano, de tal manera que la selección del siguiente jugador sea al azar.


El metodo encuentraVecino comienza con el jugador que esta inmediatamente a la izquierda y continua alrededor del círculo hasta que encuentra un jugador que aun tiene cartas.




   1: class JuegoDeLaMona(JuegoDeCartas):
   2:     ...
   3:     def encuentraVecino(self, i):
   4:         cantManos = len(self.manos)
   5:         for proximo in range(1,cantManos):
   6:             vecino = (i + proximo) % cantManos
   7:             if not self.manos[vecino].estaVacio():
   8:                 return vecino

Si por cualquier motivo encuentraVecino llegara a dar la vuelta completa al círculo sin encontrar cartas, devolvería None y eso causaría un error en alguna otra parte del programa.


Afortunadamente podemos probar que eso no va a suceder nunca (siempre y cuando se detecte correctamente el final del juego).


Hemos omitido el metodo muestraManos. Ese puede escribirlo usted mismo.


La siguiente salida proviene de una forma reducida del juego, en la cual solamente se reparten las quince cartas mas altas(desde los dieces hacia arriba) a tres jugadores. Con este mazo mas pequeño, el juego termina tras siete coincidencias, en lugar de veinticinco.







   1: >>> import cartas
   2: >>> juego = cartas.JuegoDeLaMona()
   3: >>> juego.jugar(["Allen","Jeff","Chris"])
   4: ----- Se han repartido las cartas.
   5: Mano Allen contiene
   6: Rey de Corazones
   7: Sota de Treboles
   8: Reina de Picas
   9: Rey de Picas
  10: 10 de Diamantes
  11: Mano Jeff contiene
  12: Reina de Corazones
  13: Sota de Picas
  14: Sota de Corazones
  15: Rey de Diamantes
  16: Reina de Diamantes
  17: Mano Chris contiene
  18: Sota de Diamantes
  19: Rey de Treboles
  20: 10 de Picas
  21: 10 de Corazones
  22: 10 de Treboles
  23: Mano Jeff: Reina de Corazones con Reina de Diamantes
  24: Mano Chris: 10 de Picas con 10 de Treboles
  25: ----- Se eliminaron las coincidencias, el juego comienza.
  26: Mano Allen contiene
  27: Rey de Corazones
  28: Sota de Treboles
  29: Reina de Picas
  30: Rey de Picas
  31: 10 de Diamantes
  32: Mano Jeff contiene
  33: Sota de Picas
  34: Sota de Corazones
  35: Rey de Diamantes
  36: Mano Chris contiene
  37: Sota de Diamantes
  38: Rey de Treboles
  39: 10 de Corazones
  40: Mano Allen: eligio Rey de Diamantes
  41: Mano Allen: Rey de Corazones con Rey de Diamantes
  42: Mano Jeff: eligio 10 de Corazones
  43: Mano Chris: eligio Sota de Treboles
  44: Mano Allen: eligio Sota de Corazones
  45: Mano Jeff: eligio Sota de Diamantes
  46: Mano Chris: eligio Reina de Picas
  47: Mano Allen: eligio Sota de Diamantes
  48: Mano Allen: Sota de Corazones con Sota de Diamantes
  49: Mano Jeff: eligio Rey de Treboles
  50: Mano Chris: eligio Rey de Picas
  51: Mano Allen: eligio 10 de Corazones
  52: Mano Allen: 10 de Diamantes con 10 de Corazones
  53: Mano Jeff: eligio Reina de Picas
  54: Mano Chris: eligio Sota de Picas
  55: Mano Chris: Sota de Treboles con Sota de Picas
  56: Mano Jeff: eligio Rey de Picas
  57: Mano Jeff: Rey de Treboles con Rey de Picas
  58: ----- El juego termino.
  59: La mano de Allen esta vac³a.
  60: La mano de Jeff contiene
  61: Reina de Picas
  62: La mano de Chris esta vac³a.
  63: As³ que Je® es quien perdio.

Comentarios

Entradas populares de este blog

3.11. Diagramas de pila

Para mantener el rastro de que variables pueden usarse y donde, a veces es útil dibujar un diagrama de pila. Como los diagramas de estado, los diagramas de pila muestran el valor de cada variable, pero también muestran la función a la que cada variable pertenece. Cada función se representa por una caja con el nombre de la función junto a el. Los parámetros y variables que pertenecen a una función van dentro. Por ejemplo, el diagrama de stack para el programa anterior tiene este aspecto: El orden de la pila muestra el flujo de ejecución. imprimeDoble fue llamado por catDoble y a catDoble lo invoco __main__ , que es un nombre especial de la función mas alta. Cuando crea una variable fuera de cualquier función, pertenece a main En cada caso, el parámetro se refiere al mismo valor que el argumento correspondiente. Así que parte1 en catDoble tiene el mismo valor que cantus1 en main . Si sucede un error durante la llamada a una función, Python imprime el nombre de la función ...

6.4. Tablas de dos dimensiones

Una tabla de dos dimensiones es una tabla en la que Usted elige una fila y una columna y lee el valor de la intersección. Un buen ejemplo es una tabla de multiplicar. Supongamos que desea imprimir una tabla de multiplicar para los valores del 1 al 6. Una buena manera de comenzar es escribir un bucle sencillo que imprima los múltiplos de 2, todos en una l³nea. 1: i = 1 2: while i <= 6: 3: print 2*i, '\t' , 4: i = i + 1 5: print La primera línea inicializa una variable lllamada i , que actuara como contador, o variable de bucle. Conforme se ejecuta el bucle, el valor de i se incrementa de 1 a 6. Cuando i vale 7, el bucle termina. Cada vez que se atraviesa el bucle, imprimimos el valor 2*i seguido por tres espacios. De nuevo, la coma de la sentencia print suprime el salto de línea. Despues de completar el bucle, la segunda sentencia print crea una línea nueva. La salida de este programa es: 2 4 6 8 10 12 Hasta ahora, bie...

C.3. Cartas, mazos y juegos Python

1: import random 2: class Carta: 3: listaDePalos = [ "Tr¶eboles" , "Diamantes" , "Corazones" , 4: "Picas" ] 5: listaDeValores = [ "nada" , "As" , "2" , "3" , "4" , "5" , "6" , "7" , 6: "8" , "9" , "10" , "Sota" , "Reina" , "Rey" ] 7: 8: def __init__(self, palo=0, valor=0): 9: self.palo = palo 10: self.valor = valor 11: def __str__(self): 12: return (self.listaDeValores[self.valor] + " de " +\ 13: self.listaDePalos[self.palo]) 14: def __cmp__(self, otro): 15: # controlar el palo 16: if self.palo > otro.palo: return 1 17: if self.palo < otro.palo: return -1 18: # si son del mismo palo, controlar el valor 19...