"""
Mazos y cartas.
Contiene un Mazo y una clase Carta.
.. rubric:: Tipos de mazos y cartas disponibles:
* "español": Cartas del 1 al 12 más dos comodines. Los palos son "espada",
"oro", "basto" y "copas".
* "francés": Cartas del 2 al 10 más las A, J, Q, K y dos comodines. Los palos
son "pica", "corazón", "trébol" y "diamantes".
"""
from typing import List, Union
import random
FIGURAS_POSIBLES = {}
"""
Figuras soportadas por Carta.
No incluye "comodín"
"""
PALOS_POSIBLES = {}
"""
Palos soportados por Carta.
"""
FIGURAS_POSIBLES["español"] = list(range(1, 12 + 1))
PALOS_POSIBLES["español"] = ["espada", "oro", "basto", "copas"]
FIGURAS_POSIBLES["francés"] = list(range(2, 10 + 1)) + ["A", "J", "Q", "K"]
PALOS_POSIBLES["francés"] = ["pica", "corazón", "trébol", "diamante"]
[documentos]class Mazo:
"""
Un mazo de cartas.
Al crear el mazo está vacío.
Attributes:
"""
# pep 484
def __init__(self):
self.cartas = []
[documentos] def generar(self, tipo: str = "español", juego: int = 50):
"""
Crear un mazo estándar.
.. rubric:: Tipos y Juegos disponibles
* "español": Cartas del 1 al 12 más dos comodines. Los palos son espada,
oro, basto y copas.
* 50: Todas las cartas del mazo más dos comodines.
* 48: Todas las cartas del mazo menos los dos comodines.
* 40: Todas las cartas del mazo menos los comodines, los 8 y los 9.
* 36: Todas las cartas del mazo menos los comodines, los 8, los 9 y
los 10.
* "francés": Cartas del 2 al 10 más las A, J, Q, K y dos comodines. Los
palos son pica, corazón, trébol y diamantes.
* 54: Todas las cartas del mazo más dos comodines.
* 52: Todas las cartas del mazo menos los dos comodines.
Args:
tipo: Tipo de mazo a utilizar. "español" o "francés".
juego: Número de cartas a utilizar. Los posibles juegos dependen del
tipo de mazo. Ver posibilidades abajo
Attributes:
cartas: Lista que contiene a las cartas del mazo, los primeros
elementos son los que están más abajo en el mazo y los últimos
son los que están arriba del mazo.
"""
if tipo == "español":
palos = PALOS_POSIBLES["español"]
if juego == 50:
figuras = FIGURAS_POSIBLES["español"]
self.generar_personalizado("español", figuras, palos, 2)
elif juego == 48:
figuras = FIGURAS_POSIBLES["español"]
self.generar_personalizado("español", figuras, palos, 0)
elif juego == 40:
figuras = range(1, 7 + 1) + [10]
self.generar_personalizado("español", figuras, palos, 0)
elif juego == 40:
figuras = range(1, 7 + 1)
self.generar_personalizado("español", figuras, palos, 0)
else:
raise ValueError("juego {} inválido para mazo {}"\
.format(juego, tipo))
elif tipo == "francés":
palos = PALOS_POSIBLES["francés"]
figuras = FIGURAS_POSIBLES["francés"]
if juego == 54:
self.generar_personalizado("francés", figuras, palos, 2)
elif juego == 54:
self.generar_personalizado("francés", figuras, palos, 0)
else:
raise ValueError("juego {} inválido para mazo {}"\
.format(juego, tipo))
else:
raise ValueError("tipo {} inválido".format(tipo))
[documentos] def generar_personalizado(self, tipo: str, figuras: List[Union[str, int]],
palos: List[str], cant_comodines: int) -> None:
"""
Generar mazo a partir de las figuras (números), palos y cantidad de
comodines.
Args:
tipo: Tipo de mazo a utilizar. "español" o "francés".
figuras: Figuras a utilizar, puede ser cualquier número o cualquier
string en el caso de tratarse de una letra. Ver abajo los
valores aceptados.
palos: Palos a utilizar, ver abajo los valores aceptados.
cant_comodines: Cantidad de comodines a utilizar.
.. rubric:: Valores aceptados
* "español"
* Figuras: int desde 1 al 12.
* Palos: "espada", "oro", "basto" y "copas".
* "francés"
* Figuras: int desde 2 al 10, sino puede ser un str de los posibles:
"A", "J", "Q", "K".
* Palos: "espada", "oro", "basto" y copas".
"""
# chequeo de valores obtenidos
for figura in figuras:
if figura not in FIGURAS_POSIBLES[tipo]:
raise ValueError("figura {} inválida".format(figura))
for palo in palos:
if palo not in PALOS_POSIBLES[tipo]:
raise ValueError("palo {} inválido".format(palo))
self.cartas = []
for palo in palos:
for figura in figuras:
self.cartas.append(Carta(tipo, figura, palo))
for _ in range(cant_comodines):
self.cartas.append(Carta(tipo, "comodín"))
def __str__(self):
"""
Las cartas se muestran en orden, comenzando por la superior.
"""
string = ""
for carta in reversed(self.cartas):
string += str(carta) + "\n"
return string
[documentos] def mezclar(self):
"""
Mezclar las cartas.
"""
random.shuffle(self.cartas)
[documentos] def tomar(self):
"""
Tomar una carta del mazo.
"""
return self.cartas.pop()
[documentos] def poner(self, e):
"""
Poner una carta o un mazo encima de este mazo.
Al poner un mazo se vacía al otro mazo.
"""
if type(e) == Mazo:
self.cartas.extend(e.cartas)
e.vaciar()
elif type(e) == Carta:
self.cartas.append(e)
else:
raise TypeError("argumento inválido, debe ser un mazo o una carta")
[documentos] def vaciar(self):
"""
Elimina todas las cartas del mazo.
"""
self.cartas = []
[documentos] def cant_cartas(self):
"""
Obtener la cantidad de cartas del mazo.
"""
return len(self.cartas)
[documentos]class Carta:
"""
Representa a una carta.
Attributes:
tipo: Tipo de mazo al que pertenece, "español" o "francés".
figura: Figura de esta carta, ver FIGURAS_POSIBLES. Además puede ser
"comodín".
palo: Palo al que pertenece esta carta, ver PALOS_POSIBLES. Si la figura
es "comodín", el palo es None.
Args:
tipo: Tipo de mazo al que pertenece, "español" o "francés".
figura: Figura de esta carta, ver FIGURAS_POSIBLES. Además puede ser
"comodín".
palo: Palo al que pertenece esta carta, ver PALOS_POSIBLES. Si la figura
es "comodín", el palo es None.
"""
def __init__(self, tipo, figura, palo = None):
# chequeo de valores obtenidos
if figura != "comodín":
if figura not in FIGURAS_POSIBLES[tipo]:
raise ValueError("figura {} inválida".format(figura))
if palo not in PALOS_POSIBLES[tipo]:
raise ValueError("palo {} inválido".format(palo))
else:
palo = None
self.tipo = tipo
self.figura = figura
self.palo = palo
def __str__(self):
"""
Representación de la carta, se muestra el palo y la figura en una misma
línea.
Primero el palo justificado a la izquierda y luego la figura.
"""
if self.palo is None:
return "{}".format(self.figura)
else:
return "{:>2} - {}".format(self.figura, self.palo)