234 lines
9.8 KiB
Python
234 lines
9.8 KiB
Python
|
""" Deberás programar el juego TA-TE-TI.
|
||
|
Cuando el programa comienza a correr, en la pantalla aparece el tablero de TA-TE-TI (de 3x3)
|
||
|
y un input que permite al usuario elegir el símbolo “X” o el símbolo “O”. Las “X” empiezan.
|
||
|
|
||
|
El usuario debe elegir la posición del tablero (esta posición debe ser correcta y no debe estar ocupada) donde poner
|
||
|
el símbolo en el tablero y el sistema valida si el juego termina con un ganador o en empate.
|
||
|
|
||
|
Si no hay ganador o la partida no terminó todavía en empate, el juego continúa preguntando al otro usuario que
|
||
|
seleccione la posición del tablero dónde quiere poner su símbolo y así siguiendo hasta que la partida termine
|
||
|
con un ganador o en empate.
|
||
|
|
||
|
Notas:
|
||
|
Representar el tablero como una matriz de 3x3.
|
||
|
El juego termina en empate cuando el tablero está completo y no hay ganadores."""
|
||
|
|
||
|
# Este archivo ha sido creado con fines didacticos y como entrega final del 2do modulo del Curso Aprende a Programar
|
||
|
# en Python, dictado por la Universidad Austral, atravez de Coursera
|
||
|
# @Autor: devfzn@gmail.com
|
||
|
|
||
|
import random
|
||
|
import os
|
||
|
from time import sleep
|
||
|
|
||
|
# Limpia pantalla, funciona en algunos sistemas (Shell + Python 3.8.2, Windows 10 Python3.8.4, IDLE no, y en
|
||
|
# py-charm (click derecho en el archivo (2 opciones mas abajo de Run, entrar en EDIT y seleccionar ejecutar
|
||
|
# en Emulador de Terminal, en vez de Python console.)
|
||
|
clear = lambda: os.system('clear') if os.name == 'posix' else os.system('cls')
|
||
|
limpiar_pantalla = True
|
||
|
|
||
|
""" Creación de matriz base"""
|
||
|
#matriz = [['a1', 'b1', 'c1'], ['a2', 'b2', 'c2'], ['a3', 'b3', 'c3']]
|
||
|
matriz = [['|_','|_','|_'], ['|_','|_','|_'], ['|_','|_','|_']]
|
||
|
# Creacción de dicionario vacío y lista de llaves.
|
||
|
master, llaves = {}, [x+y for x in 'abc' for y in '123']
|
||
|
|
||
|
# Preguntas para solicitar entradas de usuario
|
||
|
lado = '\tEscribe \'o\' para jugar con \'O\',\n\to \'x\' para jugar con \'X\',\n\t(\'X\' hace la primera jugada)\n\t> '
|
||
|
salir = '\tJugar Otra? (si/no)\n\t> '
|
||
|
jugada = '\tIngresa tu jugada (ej. a2)\n\t> '
|
||
|
tit_V = 'Ganaste, Felicitaciones!'
|
||
|
tit_P = ' Has perdido'
|
||
|
|
||
|
# Lista con tuplas de condiciones para ganar o perder el juego.
|
||
|
ganadoras = [('a1', 'b1', 'c1'),
|
||
|
('a2', 'b2', 'c2'),
|
||
|
('a3', 'b3', 'c3'),
|
||
|
('a1', 'a2', 'a3'),
|
||
|
('b1', 'b2', 'b3'),
|
||
|
('c1', 'c2', 'c3'),
|
||
|
('a1', 'b2', 'c3'),
|
||
|
('c1', 'b2', 'a3')]
|
||
|
|
||
|
def actualizar_matriz():
|
||
|
"""
|
||
|
Actualiza los valores en la matriz según los valores en diccionario maestro
|
||
|
:return: None
|
||
|
"""
|
||
|
x, y = 0, 0 # Variables para indices de matriz tablero
|
||
|
for valor in master.values(): # Recorre los valores del diccionario
|
||
|
if not y < 3: # Limite indice columnas
|
||
|
y = 0 # Reinicio contador columnas
|
||
|
x += 1 # Autoincremento de fila al llegar a 3ra columna
|
||
|
matriz[y][x] = valor # Asigna el valor del diccionario a la matriz (casilla)
|
||
|
y += 1 # Autoincremento de columna
|
||
|
|
||
|
def dibujar_tablero(*frase):
|
||
|
"""
|
||
|
Muestra en pantalla un string pasada como argumento, coordenadas y matriz de juego
|
||
|
:param frase: titulo a mostrar según circunstancia
|
||
|
:return: None
|
||
|
"""
|
||
|
if limpiar_pantalla:
|
||
|
clear()
|
||
|
print('\n\t', *frase, '\n\n\t\t a b c')
|
||
|
for x in range(len(matriz)):
|
||
|
print('\t\t', end=str(x+1))
|
||
|
for y in range(len(matriz[x])):
|
||
|
print(matriz[x][y], end='')
|
||
|
print('|')
|
||
|
print('\n')
|
||
|
|
||
|
|
||
|
# #####################################** ANIMACION **################################################################ #
|
||
|
|
||
|
saludo = ['\n\tBienvenido al Clasico ', '\n\n\n\t\t\"GATO!\"']
|
||
|
jugadas = [[0, 0], [1, 2], [2, 0], [1, 0], [1, 1], [2, 2], [0, 2]]
|
||
|
|
||
|
def parp_text(repets, *texto):
|
||
|
print(len(texto))
|
||
|
x, sec = 0, True
|
||
|
while x < repets:
|
||
|
for txt in texto:
|
||
|
for tx in txt:
|
||
|
clear()
|
||
|
print('\n\t', tx)
|
||
|
sleep(0.7)
|
||
|
x += 1
|
||
|
sleep(1)
|
||
|
|
||
|
def animacion():
|
||
|
actualizar_matriz()
|
||
|
for x in range(len(jugadas)):
|
||
|
if x % 2 == 0:
|
||
|
matriz[jugadas[x][0]][jugadas[x][1]] = '|X'
|
||
|
else:
|
||
|
matriz[jugadas[x][0]][jugadas[x][1]] = '|O'
|
||
|
dibujar_tablero('\"devfzn@gmail.com\"')
|
||
|
sleep(0.5)
|
||
|
|
||
|
|
||
|
animacion()
|
||
|
parp_text(2, saludo)
|
||
|
########################################################################################################################
|
||
|
|
||
|
def input_usr(pregunta, respuestas):
|
||
|
"""
|
||
|
Solicita una entrada al usuario, recive 1 string y una lista de string
|
||
|
:param pregunta: string Pregunta a realizar
|
||
|
:param respuestas: [string] Lista de posibles respuestas en mayúscula
|
||
|
:return: 'string' input de usuario validado
|
||
|
"""
|
||
|
resp = '' # Variable que recibe entrada de usuario
|
||
|
while resp not in respuestas: # Valida respuesta según 'respuestas'
|
||
|
resp = input(pregunta).upper() # Asignación entrada de usuario (mayusculas forzadas)
|
||
|
return resp
|
||
|
|
||
|
|
||
|
jugar = True # Variable que gobierna el ciclo principal (Juego)
|
||
|
while jugar: # Ciclo principal
|
||
|
global turno #
|
||
|
for llave in llaves: # Recorre las llaves y asgina '|_'(vacío) a cada item
|
||
|
master[llave] = '|_'
|
||
|
slave = master.copy() # Copia superficial del diccionario maestro
|
||
|
actualizar_matriz() # Poblar matríz con los valores del diccionario maestro
|
||
|
dibujar_tablero(' Elige el lado X - O') # Imprime matríz en pantalla
|
||
|
global p1
|
||
|
p1 = input_usr(lado, ['x', 'X', 'o', 'O']) # Asignación de entrada de usuario, P1 (Player 1)
|
||
|
titulo = 'P1 jugando con -> ' + p1
|
||
|
cambio = lambda x: 'O' if x == 'X' else 'X' # Función anónima retorna el símbolo opuesto al evaluado X,O
|
||
|
global pc
|
||
|
pc = cambio(p1) # Asignación de símbolo a jugador PC (Player Computer)
|
||
|
turno = 0 # Contador de turnos jugados
|
||
|
|
||
|
dibujar_tablero(titulo)
|
||
|
|
||
|
def turno_p1():
|
||
|
"""
|
||
|
Función que recibe una entrada de usuario y la valida
|
||
|
según la copia de las llaves del diccionario maestro.
|
||
|
Actualiza el valor en el diccionario maestro con el
|
||
|
symbolo seleccionado por el jugador PC y e xtrae la copia de 'slave'
|
||
|
:return: None
|
||
|
"""
|
||
|
jp1 = input_usr(jugada, list(x.upper() for x in list(slave.keys()))).lower()
|
||
|
slave.pop(jp1)
|
||
|
master[jp1] = '|' + p1
|
||
|
|
||
|
|
||
|
def turno_pc():
|
||
|
"""
|
||
|
Función que selecciona una llave al azar de la copia del
|
||
|
diccionario maestro y actualiza a este último con el simbolo
|
||
|
del jugador PC.
|
||
|
Despues del turo nro. 2 evalúa si hay algún espacio estrategico,
|
||
|
donde existen dos simbolos iguales, pone el tercero, priorizando
|
||
|
los pares de symbolos afines con el bando asignado.
|
||
|
:return: None
|
||
|
"""
|
||
|
if turno > 2:
|
||
|
falta, hay_par = (), False
|
||
|
for pos in ganadoras:
|
||
|
a, b, c = master[pos[0]], master[pos[1]], master[pos[2]]
|
||
|
if '|_' != a == b != c == '|_':
|
||
|
falta = (a, pos[2])
|
||
|
hay_par = True
|
||
|
if a == pc + '|_':
|
||
|
break
|
||
|
elif '|_' != a == c != b == '|_':
|
||
|
falta = (a, pos[1])
|
||
|
hay_par = True
|
||
|
if a == pc + '|_':
|
||
|
break
|
||
|
elif '|_' != c == b != a == '|_':
|
||
|
falta = (c, pos[0])
|
||
|
hay_par = True
|
||
|
if c == pc + '|_':
|
||
|
break
|
||
|
if hay_par:
|
||
|
jpc = falta[1]
|
||
|
else:
|
||
|
jpc = ''.join(random.choice(list(slave.keys())))
|
||
|
else:
|
||
|
jpc = ''.join(random.choice(list(slave.keys())))
|
||
|
slave.pop(jpc)
|
||
|
master[jpc] = '|' + pc
|
||
|
|
||
|
|
||
|
def eval_term():
|
||
|
"""
|
||
|
Función que evalua si se cumplen las condiciones para terminar la partida.
|
||
|
Compara los valores el diccionario 'maestro' según las llaves en las tuplas,
|
||
|
de la lista 'ganadaoras'. Asigna un titulo y un valor al booleano 'termino'
|
||
|
:return: None
|
||
|
"""
|
||
|
global titulo
|
||
|
global termino
|
||
|
for g in ganadoras:
|
||
|
test = master[g[0]]
|
||
|
test2 = '|' + p1
|
||
|
if '|_' != test == master[g[1]] == master[g[2]]:
|
||
|
termino = True
|
||
|
titulo = tit_V if test2 == '|X' == test else tit_V if test2 == '|O' == test else tit_P
|
||
|
if turno > 8 and not termino:
|
||
|
termino, titulo = True, '\t EMPATE'
|
||
|
|
||
|
|
||
|
X = p1 == 'X' # Booleano indica si jugador 1 es 'X'
|
||
|
termino = False # Booleano que gobierna ciclo de jugadas
|
||
|
while not termino: # Ciclo de jugadas
|
||
|
turno_p1() if X else turno_pc() # Alterna el turno del Player1 y PC, segun 'X'
|
||
|
X = not X # Alterna el booleano 'X'
|
||
|
turno += 1
|
||
|
eval_term()
|
||
|
actualizar_matriz()
|
||
|
dibujar_tablero(titulo)
|
||
|
|
||
|
resp = input_usr(salir, ['N', 'NO', 'S', 'SI'])
|
||
|
jugar = resp in 'SI' # Actualización del booleano que gobierna while principal
|
||
|
|
||
|
autor = ['', '\n\n\t "devfzn@gmail.com\"']
|
||
|
parp_text(4, autor)
|
||
|
|
||
|
#exit()
|
||
|
#quit()
|