Mejorado post clase

mail@pastecode.io avatar
unknown
python
2 years ago
8.6 kB
2
Indexable
# Rodrigo Sampedro Casis

import random
 
def display_board(board):
    #funcion para pintar el tablero
    # para acceder a la primera casila (fila 0 columna 0) segunda casilla (fila 0 columna 1) ...
    print("\n")
    for c in range(0,3):
        print(f"{board[c][0]} | {board[c][1]} | {board[c][2]}                                    {c*3+1} | {c*3+2} | {c*3+3} ")
        if(c != 2):
             print("-","*","-","*","-","                                   -","*","-","*","-")

    print("\n")
    print("--------------------------------------------------------------------------")
 
 
def enter_move(board): 
    #funcion para que el usario introduzca su movimiento
    move_done = False
    while(not move_done):
        introduccion = input("Introduzca un numero del 1 - 9 para la posicion del movimiemto.")
        # check numerico
        if( introduccion.isnumeric()):
            movimiento = int(introduccion)
            # posibles movimientos libres
            posibles_movimientos = list_free_fields(board)
            # check es un numero entre 1-9 y esta disponible
            if(0<movimiento<10 and (movimiento in posibles_movimientos)):
                do_movement(board, movimiento,"Jugador", "X")
                move_done = True
            else:
                # indicar al usuario que se ha equivocado en el numero o no esta disponible
                print("Has introducido un numero invalido, recuerde 1-9 y que este disponible.")
    

def list_free_fields (board):
    # funcion para devolver los posibles movimientos disponibles
    lista_vacia=[]
    for posicion in range (1,10):
        fila = (posicion - 1) // 3
        columna = (posicion -1 ) % 3
        #si la casilla esta vacia " " es un movimiento disponible
        if(board[fila][columna]==" "):
            lista_vacia.append(posicion)
    return lista_vacia
 
 
def victory_for(board, sign):
   #funcion para saber si la jugada hace tre en raya
   for i in range (0,3):
        # comprobamos jugadas en horizontal y en vertical
        if(board[i][0]==board[i][1]==board[i][2]==sign or board[0][i]==board[1][i]==board[2][i]==sign):
            return True
    #c comprobamos jugadas en diagonal
   if(board[0][0]==board[1][1]==board[2][2]==sign or board[0][2]==board[1][1]==board[2][0]==sign):
        return True
   else:
        return False
 
 
def do_movement(board, movement, player, sign):
    # funcion que ejecuta el movimiento en el tablero pasado por argumento
    fila = (movement - 1) // 3
    columna = (movement -1 ) % 3
    board[fila][columna] = sign
    # encaso de movimiento real lo muestra por pantalla
    if(player!="simulacion"):
        print(f"Movimiento de la {player} {movement}")


def draw_move(board):
    # funcion que ejecuta el movimiento del 'computador' en el tablero

    #busca todos los posibles movimientos
    casillas_vacias = list_free_fields(board)
    # la inteligencia (algoritmica) busca jugada mas interesante para O
    movimiento = inteligencia(board, "0", "X")
    # ejecuta movimiento en el tablero
    do_movement(board, movimiento,"Computadora", "0")
    # muestra tablero con movimiento ejecutado
    display_board(board)


def inteligencia(board, jugador1, jugador2):
    # funcion donde incluir el algoritmo de inteligencia del computador

    # posibles jugadas del tablero
    casillas_vacias = list_free_fields(board)
    jugadas_ganadoras = []
    jugadas_tapon = []

    # ejecutamos cada uno de los posibles jugadas para evaluarlas
    # 1º objetivo es ganar en la jugada
    # 2º objetivo es evitar que el usuario gane, ya que la computadora siempre juega segunda
    # 3º objetivo obtener una jugada estrategica
    # 4º si no hay un objetivo alcanzable, jugar con aleatoriedad
    for movimiento in casillas_vacias:
        # creamos una copia del tablero sobre la que hacer
        #  simulaciones de jugadas
        simulacion = [row[:] for row in board ]
        # Ganar => simular si movimiento gana computadora       
        do_movement(simulacion, movimiento,"simulacion", jugador1)
        if (victory_for(simulacion, jugador1)==True):
            # retornar jugada ganadora
            jugadas_ganadoras.append(movimiento)

        # Taponar => simular si el usuario ganar con movimiento
        simulacion = [row[:] for row in board ]
        do_movement(simulacion, movimiento,"simulacion", jugador2)    
        if (victory_for(simulacion, jugador2)==True):
            # taponar jugada futura del usuario
            jugadas_tapon.append(movimiento)     

    # Ejecuto jugadas segun mis objetivos
    if(len(jugadas_ganadoras)>0):
        return jugadas_ganadoras[0]
    if(len(jugadas_tapon)>0):
        return jugadas_tapon[0]
        
    # checkear que el centro  esta libre, punto estrategico
    if( 5 in casillas_vacias):
        # con esta inteligencia si el usuario no escoge el centro
        # la maquina nunca pierde, puesto que el usuario ya no puede hacer
        # doble jugada ganadora
        return 5
    #elseif TODO: si juego primero, estrategia de esquinas para doble jugada ganadora
    # esta jugada no es aplicable puesto que lamaquina siempre juega 2º
    else:            
        # Simulacionas de jugadas a 2 iteraciones
        # (esto hace a la maquina algo mas inteligente, para priorizar aquellas
        # jugadas donde un error humano a 2 iteraciones, de las que no existe amenaza
        # 
        # Por lo tanto este else puede ser obviado por una inteligencia menos lista
        # pero mas rapida
        for movimiento in casillas_vacias:
            if(len(casillas_vacias)>3):
                # simulo movimiento actual
                #  + una iteracion mas de inteligencia
                simulacion = [row[:] for row in board ]
                do_movement(simulacion, movimiento,"simulacion", jugador1)
                # calculo siguiente mejor movimiento de mi adversario
                # que es ganar el o taponarme a mi
                movimiento2 = inteligencia(simulacion, jugador2, jugador1)
                
                simulacion2 = [row[:] for row in simulacion ]
                # evaluo si su movimiento es un tapon
                do_movement(simulacion2, movimiento2,"simulacion", jugador1)    
                if (victory_for(simulacion2, jugador1)==True):
                    # retornar jugada ganadora a 2 iteraciones
                    return movimiento
                # Si su jugada es aleatoria o me gana el a 2 iteraciones no me interesa
            # este movimineto, pasar al siguiente posibilidad


    # si no existe un objetivo alcanzable random entre las posibles jugadas
    return casillas_vacias[random.randint(0, len(casillas_vacias)-1)]

  
 
  
def jugar():
    # esta funcion es el punto de entrada
    # ejecuta la creacion del tablero y los mensajes iniciales
    #  y realiza las llamadas a las diferentes funciones para ejecutar el juego

    # creacion de tablero e inicio del juego
    tablero = [[" " for c in range(3)] for d in range(3)]
    print("Vamos a jugar al 3 en raya!!!")
    display_board(tablero)

    # TODO: interesante mejora, flip a coin y  que pueda empezar la maquina o el usuario

    # codigo recurrente hasta que gane unjugador o no existan mas jugadas
    no_box = False
    while(not no_box):
        # juega usuario
        enter_move(tablero)
        # comprobar si usuario gana
        if (victory_for(tablero, "X")==True):
            print (" \n *** Has ganado *** \n")
            break
        
        # comprobar si es la ultima jugada por que no quedan casillas
        if (len(list_free_fields(tablero)) == 0):
            print (" \n *** Empate *** \n")
            break

        # juega la computadora
        draw_move(tablero)
        # comprobar si la computadora ha ganado
        if (victory_for(tablero, "0")==True):
            print ("Has perdido")
            break

        #comprobar si existen mas juegadas por parte del usuario
        #  como el usuario siempre juega primero y el tablero es impar
        #  y se juega a bloques de 2 jugadas
        # este caso no se puede dar, solo util si la maquina puede jugar primero
        #if(len(list_free_fields(tablero)) == 0):
        #    print ("Empate")
        #    no_box = True
    
    # mostramos final del tablero
    display_board(tablero)
 

 # llamada ala funcion principal del script jugar ()  
jugar()