Clase Numero 14 – Ejercicio Black jack Completo

Ejercicio Black Jack Completo

"""
Juego de Black jack de cero
con CLASES, OBJETOS y METODOS
"""

"""
Primero:
importo modulo, creo las variables globales y defino un True para controlar los WHILE
"""
# importo el modulo random
import random as R

# declaro las variables a usar para construir el mazo y un booleano en True para controlar los While
# palos - para hearts, diamonds, spades y clubs
# numeros - nombre valor de la carta
# valores - valores numericos asociados a las cartas

palos = ('♥', '♦', '♣', '♠')
numeros = ("Dos", "Tres", "Cuatro", "Cinco", "Seis", "Siete", "Ocho", "Nueve", "Diez", "Jack", "Queen", "King", "As")
valor = {'Dos':2, 'Tres':3, 'Cuatro':4, 'Cinco':5, 'Seis':6, 'Siete':7, 'Ocho':8, 'Nueve':9, 'Diez':10, 'Jack':10,
         'Queen':10, 'King':10, 'As':11}

jugando = True

"""
Segundo:
Creamos la CLASE CARTAS
El OBJETO "carta" solo necesita DOS ATRIBUTOS;
"palos" y "numeros"
Ademas del metodo cartas_init, agegamos OTRO metodo
_str_method que cuando le pidamos mostrar el resultado (print)
#nos devuelva un string en forma "Dos de ♥" , por ejemplo
"""

class Cartas:
    
    def __init__(self, palo, numero):
        self.palo = palo
        self.numero = numero
        
    def __str__(self):
        return self.numero + " de " + self.palo
    
"""
Tercero:
Creamos una CLASE MAZO
Almacenamos 52 OBJETOS CARTA en una LISTA
que podremos mezclar mas tarde on R.shuffle()
"""
# primero "instanciamos" las Cartas (palos y numeros)
# instanciar = Cartas es un objeto compuesto de varias instancias (As de pica,
# de corazones, etc -> 52 instancias) asi que lo instanciamos con un FOR
# for palos in palos:
    # for numeros in numeros:
    
class Mazo():
    
    def __init__(self):
        self.mazo = [] # comenzamos con una LISTA vacia
        for palo in palos:
            for numero in numeros:
                self.mazo.append(Cartas(palo, numero)) # CONSTRUIMOS el OBJETO CARTAS y los agregamos a la lista
                
    def __str__(self):
        mazo_completo = '' # comienza con una cadena vacia
        for carta in self.mazo:
            mazo_completo += '\n' + carta.__repr__() # Agrego cada OBJETO CARTA print string al mazo
        return "El Mazo Tiene: " + mazo_completo
    
    def shuffle(self):
        R.shuffle(self.mazo)
                
    def barajar(self):
        una_carta = self.mazo.pop()
        return una_carta
    
"""   
Podemos testear que el Mazo esta ok llamandolo
y devolvera algo como
<__main__.Mazo object at 0x0406BD50>
"""   
#test_mazo = Mazo()
#print (test_mazo)
 
"""
Cuarto:
Craer una CLASE MANO
ADEMAS de tener OBJETOS Cartas barajados desde el MAZO,
la CLASE MANO puede usarse par calcular el VALOR e esas Cartas
usando el diccionario VALORES definido al principio.
Tambien ajustamos el valor de los ASES aca
"""

class Mano():
    def __init__(self):
        self.cartas = [] # comienza con LISTA vacia, como la Clase Mazo
        self.valores = 0 # comienza con valor cero
        self.ases = 0 # atributo "ases" definido para controlar valor de los ases
    
    def agregar_carta(self,carta):
        self.cartas.append(carta)
        self.valores += valor [carta.numero]
        if carta.palo == "As":
            self.ases += 1 # se agrega a self.ases
        
    def ajuste_por_ases(self):
        while self.valores > 21 and self.ases:
            self.valores -= 10
            self.ases +=1
            
"""
Creamos una clase Fichas para hacer un seguimiento
de las fichas del jugador, apuestas y ganancias
"""
class Fichas:
    
    def __init__(self):
        self.total = 100 # valor inicial
        self.apuesta = 0
        
    def gana_apuesta(self):
        self.total += self.apuesta
        
    def pierde_apuesta(self):
        self.total -= self.apuesta
        
"""
Sexto:
Crear funcion para tomar apuestas
Como pedimos valores ENTEROS podemos usar TRY/EXCEPT
Usamos un WHILE preguntando valor
hasta que el user ingrese un entero que este
DENTRO de la cantidad de fichas que posee
y recordar comprobar que NO se pase
de la cantidad de fichas que posee al apostar
"""
def tomar_apuestas(fichas):
    
# con el WHILE forzamos a pedir un ingreso HASTA que sea un numero entero
    
    while True:
        try:
            fichas.apuesta = int (input("Cuantas Fichas desea apostar? "))
        except ValueError:
            print ("Solo se aceptan NUMEROS: ")
        else:
            if fichas.apuesta > fichas.total:
                print ("Solo tiene" , fichas.total, "cantidad de fichas")
            else:
                break
            
"""
Septimo:
Escribir una funcion que acepte HITS (pedir una carta mas)
Esta Funcion DEBE aeptar el MAZO y la MANO del jugador como argumentos,
ademas asignamos "jugando" como variable global.
Si el jugador Pide (hit), usa la funcion. Si el jugador PASA (stand)
la variable "jugando" pasa a ser False
"""
def hit_or_stand (mazo, mano):
    global jugando # para controlar el WHILE que viene
    
    while True:
        x = input ("Su turno: Hit o Stand (Pide o Pasa?) -> 'h' o 's': ")
        
        if x[0].lower == 'h':
            hit(mazo, mano) # funcion hit definida anteriormente
            
        elif x[0] == 's' :
            print ("Jugador Pasa (Stand). Turno del Dealer: ")
            jugando = False
            
        else:
            print ("No se entendio, intente nuevamente")
            continue
        break
    
"""
Noveno:
Escribir funcion que MUESTRE cartas
Cuando comienza el juego y luego de cada
vez que }el jugador toma una carta
la primer carta del dealer esta oculta
y TODAS las cartas de los jugadores estan visibles
DESPUES de la mano, cundo finaliza, hay que msotrar
TODAS las cartas de cada jugador y del Dealer
Por supuesto  mostrar los totales de cada mano
"""
      
def mostrar_parciales(jugador, dealer):
    print("\nMano del Dealer: ")
    print("<Carta Oculta>")
    print(" ", dealer.cartas[1])
    print("\nMano del Jugador: ", *jugador.cartas, sep="\n")
    
def mostrar_todo(jugador, dealer):
    print("\nMano del Dealer: ", *dealer.cartas, sep="\n")
    print("Mano del Dealer= ", dealer.valores)
    print("\nMano del Jugador: ", *jugador.cartas, sep="\n")
    print("Mano del Jugador= ", jugador.valores)


"""
Funcion para manejar el fin del juego
Psar Mano del Dealer, mano del Jugador y fichas
"""
def jugador_se_pasa(jugador, dealer, fichas):
    print("Jugador se PASO")
    fichas.pierde_apuesta()
    
def jugador_gana(jugador, dealer, fichas):
    print("Jugador ********GANA********")
    fichas.gana_apuesta()
    
def dealer_se_pasa(jugador, dealer, fichas):
    print("Dealer se PASA")
    fichas.gana_apuesta()
    
def dealer_gana(jugador, dealer, fichas):
    print("Dealer ********GANA********")
    fichas.gana_apuesta()
    
def empate(jugador, dealer):
    print("///EMPATE///")
    
"""
Ultimo paso; el Juego
"""
while True:
    
# Mensaje de apertura y saludo inicial
    print("Bienvenido a BLACK JACK! Intenta llegar tan cerca de 21 como puedas\n\
el Dealer PIDE hasta que suma 17 y luego se PLANTA. El AS vale UNO u ONCE segun el caso")
    
# Creamos Mazo, mezclamos cartas y repartimos DOS a cada jugador
    mazo = Mazo()
    mazo.shuffle()
    
    jugador_mano = Mano()
    jugador_mano.agregar_carta(mazo.barajar())
    jugador_mano.agregar_carta(mazo.barajar())
    
    dealer_mano = Mano()
    dealer_mano.agregar_carta(mazo.barajar())
    dealer_mano.agregar_carta(mazo.barajar())
    

    # Setear las Fichas del jugador
    jugador_fichas = Fichas() # lo que definimos en su momento: 100 fichas

    # Pedir al jugador su apuesta
    tomar_apuestas(jugador_fichas)

    # mostrar cartas manteniendo UNA del Dealer oculat
    mostrar_parciales(jugador_mano, dealer_mano)

    while jugando: # rellamamos a esta funcion dede hit_or_stand
    
        # jugador PASA o PIDE
        hit_or_stand(mazo, jugador_mano)
    
        # mostrar cartas MENOS una del dealer
        mostrar_parciales(jugador_mano, dealer_mano)
    
        # si el jugador se pasa mostar mensaje y romper loop
        if jugador_mano.valores > 21:
            jugador_se_pasa(jugador_mano, dealer_mano, jugador_fichas)
            break
    
        # si el jugador NO se pasa, juega el Dealer hasta alcanzar 17
    if jugador_mano.valores <= 21:
        
        while dealer_mano.valores < 17:
            hit_or_stand(mazo,dealer_mano)
                       
            # mostrar todas las cartas
            mostrar_todo(jugador_mano, dealer_mano)
        
            # mostrar los diferentes escenarios de resultados
        if dealer_mano.valores > jugador_mano.valores:
            dealer_gana(jugador_mano, dealer_mano, jugador_fichas)
            
        elif dealer_mano.valores > jugador_mano.valores:
            dealer_gana(jugador_mano, dealer_mano, jugador_fichas)
        
        elif dealer_mano.valores < jugador_mano.valores:
            jugador_gana(jugador_mano, dealer_mano, jugador_fichas)
        
        else:
            empate(jugador_mano, dealer_mano)
        
        
    # Inform Player of their chips total
    print("\nJuagdor GANO! -> Pozo acumulado = ", jugador_fichas.total)
    
    # Ask to play again
    new_game = input("Otra Partida? ? Ingrese 'y' or 'n'")
    if new_game[0].lower() == 'y':
        playing = True
        continue
    else:
        print('Gracias por Jugar! ')

        break
        

Resultado

>>> %Run Black_Jack_full_de_cero_OK.py
Bienvenido a BLACK JACK! Intenta llegar tan cerca de 21 como puedas
el Dealer PIDE hasta que suma 17 y luego se PLANTA. El AS vale UNO u ONCE segun el caso
Cuantas Fichas desea apostar? 99

Mano del Dealer: 
<Carta Oculta>
  Diez de ♥

Mano del Jugador: 
Cinco de ♥
Dos de ♥
Su turno: Hit o Stand (Pide o Pasa?) -> 'h' o 's': s
Jugador Pasa (Stand). Turno del Dealer: 

Mano del Dealer: 
<Carta Oculta>
  Diez de ♥

Mano del Jugador: 
Cinco de ♥
Dos de ♥
Dealer ********GANA********

Juagdor GANO! -> Pozo acumulado =  199
Otra Partida? ? Ingrese 'y' or 'n'

Leave a Reply

Your email address will not be published. Required fields are marked *