# Rodrigo Sampedro Casis
# Ejercicio mejorado post clase
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)
# ejecutamos cada uno de los posibles jugadas para evaluarlas
# 1º objetivo es evitar que el usuario gane, ya que la computadora siempre juega segunda
# 2º objetivo es ganar en la jugada
# 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
# 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
return movimiento
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
return movimiento
# 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 taponarme a mi o ganar el
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()