Last active
November 18, 2016 22:42
-
-
Save NekoTashi/22527f101cc73cfac63bb96c0ded1b4e to your computer and use it in GitHub Desktop.
Tablero.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-,-,-,-,-,*,- | |
-,X,X,*,-,1,- | |
-,-,*,4,*,X,- | |
-,*,X,*,3,*,- | |
-,X,-,1,-,-,- | |
-,2,-,-,1,X,- | |
-,-,-,-,*,-,- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from copy import copy | |
from pprint import pprint | |
OPCION_INVALIDA = 'Esa opción no es válida, por' \ | |
'favor escoja una de las opciones.' | |
COORDENADA_INVALIDA = 'Coordenada inválida, utilice el ' \ | |
'formato dicho anteriormente.' | |
PARTIDAS_GUARDADAS = 'partidas_guardadas' | |
class Tablero(object): | |
def __init__(self, nombre): | |
""" | |
Lee el archivo desde la variable nombre | |
X = celdas negras | |
4 = celda negra con información | |
- = celdas blancas | |
* = celdas blancas con ampolletas | |
, = separación de columnas | |
""" | |
self.nombre = nombre | |
self.tablero = [] | |
self.tablero_resuelto = False | |
self.intentos_correctos = 0 | |
self.intentos_incorrectos = 0 | |
self.tablero_iluminado = None | |
self.cargar_tablero(nombre) | |
def tablero_fuera_de_rango(self, i, j): | |
""" | |
Verifica si la asignación de la | |
ampolleta está fuera o no de rango. | |
""" | |
filas = len(self.tablero) | |
columnas = len(self.tablero[0]) | |
if i not in range(filas) or j not in range(columnas): | |
return True | |
return False | |
def tiene_celda_negra(self, i, j): | |
""" | |
Verifica si la celda tiene celda negra. | |
""" | |
return self.tablero[i][j] in ['X', '0', '1', '2', '3', '4'] | |
def tiene_restriccion_celda_negra(self, i, j): | |
""" | |
Verifica si la celda tiene celda negra con restricción. | |
""" | |
return self.tablero[i][j] in ['0', '1', '2', '3', '4'] | |
def tiene_ampolleta(self, i, j): | |
""" | |
Verifica si la celda tiene ampolleta. | |
""" | |
return self.tablero[i][j] == '*' | |
def excede_restriccion_celda_negra(self, i, j): | |
""" | |
Verifica si están ocupadas todas las celdas con | |
ampolletas de la restricción de celda negra. | |
""" | |
maximo_ampolletas_adyacentes = int(self.tablero[i][j]) | |
cantidad_ampolletas_adyacentes = 0 | |
if self.tiene_ampolleta(i - 1, j): | |
cantidad_ampolletas_adyacentes += 1 | |
if self.tiene_ampolleta(i + 1, j): | |
cantidad_ampolletas_adyacentes += 1 | |
if self.tiene_ampolleta(i, j - 1): | |
cantidad_ampolletas_adyacentes += 1 | |
if self.tiene_ampolleta(i, j + 1): | |
cantidad_ampolletas_adyacentes += 1 | |
if cantidad_ampolletas_adyacentes >= maximo_ampolletas_adyacentes: | |
return True | |
return False | |
def existe_restriccion_celda_negra(self, i, j): | |
""" | |
Retorna True si existe restricción de celda negra. | |
""" | |
try: | |
if self.tiene_restriccion_celda_negra(i - 1, j): | |
return self.excede_restriccion_celda_negra(i - 1, j) | |
except IndexError: | |
return False | |
try: | |
if self.tiene_restriccion_celda_negra(i + 1, j): | |
return self.excede_restriccion_celda_negra(i + 1, j) | |
except IndexError: | |
return False | |
try: | |
if self.tiene_restriccion_celda_negra(i, j - 1): | |
return self.excede_restriccion_celda_negra(i, j - 1) | |
except IndexError: | |
return False | |
try: | |
if self.tiene_restriccion_celda_negra(i, j + 1): | |
return self.excede_restriccion_celda_negra(i, j + 1) | |
except IndexError: | |
return False | |
return False | |
def existe_ampolleta_vecina(self, i, j): | |
""" | |
Revisa todas las direcciones vecinas de una celda | |
para ver si existe una ampolleta. | |
""" | |
largo_filas = range(len(self.tablero)) | |
largo_columnas = range(len(self.tablero[0])) | |
# arriba | |
for idx in largo_filas[1:]: | |
try: | |
if self.tablero_fuera_de_rango(i - idx, j): | |
break | |
if self.tiene_celda_negra(i - idx, j): | |
break | |
if self.tiene_ampolleta(i - idx, j): | |
print(i - idx, j) | |
return True | |
except IndexError as e: | |
print('1. {}'.format(e)) | |
break | |
# abajo | |
for idx in largo_filas[1:]: | |
try: | |
if self.tablero_fuera_de_rango(i + idx, j): | |
break | |
if self.tiene_celda_negra(i + idx, j): | |
break | |
if self.tiene_ampolleta(i + idx, j): | |
return True | |
except IndexError as e: | |
print('2. {}'.format(e)) | |
break | |
# izquierda | |
for idx in largo_columnas[1:]: | |
try: | |
if self.tablero_fuera_de_rango(i, j - idx): | |
break | |
if self.tiene_celda_negra(i, j - idx): | |
break | |
if self.tiene_ampolleta(i, j - idx): | |
return True | |
except IndexError as e: | |
print('3. {}'.format(e)) | |
break | |
# derecha | |
for idx in largo_columnas[1:]: | |
try: | |
if self.tablero_fuera_de_rango(i, j + idx): | |
break | |
if self.tiene_celda_negra(i, j + idx): | |
break | |
if self.tiene_ampolleta(i, j + idx): | |
return True | |
except IndexError as e: | |
print('4. {}'.format(e)) | |
break | |
# no existe ampolleta vecina | |
return False | |
def tablero_completo(self): | |
""" | |
Retorna True si el tablero está completo, | |
y False en caso contrario | |
""" | |
i, j = 0, 0 # punto de partida | |
resultado = self.resolver_tablero(i, j) | |
return resultado | |
def celda_esta_iluminada(self, i, j): | |
""" | |
Retorna True si la celda de la i-ésima fila y j-ésima columna | |
se encuentra iluminada. | |
""" | |
return self.existe_ampolleta_vecina(i, j) | |
def asignacion_valida(self, i, j): | |
""" | |
Retorna True si se puede poner una ampolleta en la celda de la | |
i-iésima fila y j-esima columna considerando el estado actual del | |
tablero. | |
""" | |
# if self.tiene_ampolleta(i, j): | |
# print('Existe una ampolleta.') | |
# return False | |
if self.tiene_celda_negra(i, j): | |
print('-> Tiene celda negra.') | |
return False | |
if self.existe_restriccion_celda_negra(i, j): | |
self.intentos_incorrectos += 1 | |
print('-> Existe restricción de celda negra.') | |
return False | |
if self.tiene_ampolleta(i, j): | |
self.intentos_incorrectos += 1 | |
print('-> Ya existe una ampolleta') | |
return False | |
if self.existe_ampolleta_vecina(i, j): | |
self.intentos_incorrectos += 1 | |
print('-> Existe ampolleta vecina.') | |
return False | |
print('-> Asignación válida.') | |
self.intentos_correctos += 1 | |
return True | |
def resolver_tablero(self, i, j): | |
""" | |
Resuelve de manera recursiva el tablero. | |
""" | |
print(i, j) | |
filas = len(self.tablero) | |
columnas = len(self.tablero[0]) | |
# si la coordenada (j) sale del rango de las columnas | |
# significa que terminó por recorrer el arreglo bidimensional | |
# por lo tanto, devolverá un True dado que todo se encuentra iluminado | |
if range(columnas)[-1] < j: | |
return True | |
# esta es la lógica de iteración del arreglo | |
# para verificar que todo esté iluminado | |
if i in range(filas): | |
if self.tiene_celda_negra(i, j) or self.celda_esta_iluminada(i, j): | |
return self.resolver_tablero(i + 1, j) | |
return False | |
else: | |
if self.tiene_celda_negra(6, j) or self.celda_esta_iluminada(6, j): | |
return self.resolver_tablero(6, j + 1) | |
return False | |
def tablero_resuelto(self): | |
""" | |
Retorna True si el tablero está completo. | |
El tablero está completo cuando todas las | |
celdas blancas están iluminadas. | |
""" | |
# dada la lógica de esta aplicación, un tablero completo | |
# siempre va a ser un tablero resuelto | |
return self.tablero_completo() | |
def cargar_tablero(self, nombre): | |
""" | |
Carga el tablero en una propiedad de la clase. | |
""" | |
lineas = open(nombre).read().splitlines() | |
for linea in lineas: | |
self.tablero.append(linea.split(',')) | |
def colocar_ampolleta(self, i, j): | |
""" | |
Coloca una ampolleta dentro del tablero. | |
""" | |
if self.tablero_fuera_de_rango(i, j): | |
print('¡¡¡Asignación fuera de rango del tablero.!!!') | |
# elif self.tiene_ampolleta(i, j): | |
# self.tablero[i][j] = '-' | |
# print('¡¡¡Se ha eliminado una ampolleta.!!!') | |
elif not self.asignacion_valida(i, j): | |
print('¡¡¡La asignación no es válida.!!!') | |
else: | |
self.tablero[i][j] = '*' | |
print('Se ha colocado una ampolleta con éxito.') | |
def salvar_partida(self, nombre): | |
""" | |
Guarda la partida actual. | |
""" | |
if not nombre.endswith('.txt'): | |
partida = '{}/{}.txt'.format(PARTIDAS_GUARDADAS, nombre) | |
f = open(partida, 'w') | |
for fila in self.tablero: | |
f.write('{}\n'.format(','.join(fila))) | |
f.close() | |
def jugar(tablero): | |
while(True): | |
print('****************************') | |
pprint(tablero.tablero) | |
print( | |
'Lleva {} intentos correctos y ' | |
'{} intentos incorrectos'.format( | |
tablero.intentos_correctos, | |
tablero.intentos_incorrectos, | |
) | |
) | |
print('Que quiere hacer?') | |
print('1. Realizar jugada') | |
print('2. Resolver tablero') | |
print('3. Eliminar una ampolleta') | |
print('4. Prender luces') | |
print('5. Guardar partida actual') | |
print('6. Salir del juego') | |
accion = int(input('>>> ')) | |
if accion == 1: | |
while(True): | |
print( | |
'Ingresar fila y columna separado ' | |
'por una coma (ej. \'1, 2\'): ' | |
) | |
try: | |
i, j = input('>>> ').split(',') | |
i, j = int(i), int(j) | |
print('-------------- NOTAS --------------') | |
tablero.colocar_ampolleta(i, j) | |
print('-----------------------------------') | |
break | |
except Exception as e: | |
print(e) | |
print(COORDENADA_INVALIDA) | |
if accion == 2: | |
if tablero.tablero_completo() is True: | |
print('+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+') | |
print('--- El tablero a sido resuelto con éxito. ---') | |
print('+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+') | |
break | |
else: | |
print('------------------------------------------------') | |
print('--- El tablero no a sido resuelto con éxito. ---') | |
print('------------------------------------------------') | |
continue | |
if accion == 3: | |
while(True): | |
print( | |
'Ingresar fila y columna separado ' | |
'por una coma (ej. \'1, 2\') para ' | |
'eliminar una ampolleta: ' | |
) | |
try: | |
i, j = input('>>> ').split(',') | |
i, j = int(i), int(j) | |
if tablero.tablero[i][j] == '*': | |
tablero.tablero[i][j] = '-' | |
print('Se ha eliminado una ampolleta.') | |
break | |
else: | |
print('En la celda que eligió no hay una ampolleta.') | |
except: | |
print(COORDENADA_INVALIDA) | |
if accion == 4: | |
pass | |
if accion == 5: | |
while(True): | |
print('Escoja un nombre para guardar su partida.') | |
nombre_partida_salvada = str(input('>>> ')) | |
tablero.salvar_partida(nombre_partida_salvada) | |
return | |
if accion == 6: | |
print('Saliendo de la partida...') | |
return | |
def nueva_partida(): | |
dificultades = {1: 'facil.txt', 2: 'medio.txt', 3: 'dificil.txt'} | |
while(True): | |
print('Que dificultad quiere jugar ?') | |
print('1. Facil') | |
print('2. Medio') | |
print('3. Dificil') | |
print('4. Salir') | |
while(True): | |
try: | |
opcion = int(input('>>> ')) | |
if opcion == 4: | |
return | |
elif opcion in dificultades.keys(): | |
archivo = dificultades[opcion] | |
tablero = Tablero(archivo) | |
jugar(tablero) | |
else: | |
break | |
return | |
except: | |
break | |
def cargar_partida(): | |
while(True): | |
partidas = list(enumerate(os.listdir(PARTIDAS_GUARDADAS))) | |
index_partidas = [partida[0] for partida in partidas] | |
if partidas: | |
# lista las partidas disponibles | |
index_salir = index_partidas[-1] + 1 | |
print('Qué partida desea cargar ?') | |
for index, archivo in partidas: | |
print('{}. {}'.format( | |
index, archivo.split('.')[0].capitalize())) | |
print('{}. Salir'.format(index_salir)) | |
# carga la opcion elegida por el usuario | |
try: | |
opcion = int(input('>>> ')) | |
# salir | |
if index_salir == opcion: | |
return | |
# escoje el tablero que elijió el usuario | |
for index, archivo in partidas: | |
if index == opcion: | |
tablero = Tablero('{}/{}'.format( | |
PARTIDAS_GUARDADAS, archivo)) | |
jugar(tablero) | |
# si la opción no es válida, continuar con el while | |
continue | |
except: | |
# si la opción no es válida, continuar con el while | |
continue | |
else: | |
# salir de inmediato si no se encuentra ninguna partida | |
print('No tiene partidas guardadas') | |
return | |
def main(): | |
# crear el archivo donde se | |
# guardan los tableros salvados | |
# en caso de que exista, no hacer nada | |
if not os.path.exists(PARTIDAS_GUARDADAS): | |
os.makedirs(PARTIDAS_GUARDADAS) | |
# akari | |
print('***** Bienvenido a Akari *****') | |
while(True): | |
print('Que quieres hacer?') | |
print('1. Jugar una nueva partida') | |
print('2. Jugar una partida guardada anteriormente') | |
print('3. Salir') | |
# nueva partida | |
try: | |
opcion = int(input('>>> ')) | |
if opcion == 3: | |
print('Adiós! :)') | |
return | |
if opcion in [1, 2]: | |
if opcion == 1: | |
nueva_partida() | |
if opcion == 2: | |
cargar_partida() | |
else: | |
print(OPCION_INVALIDA) | |
continue | |
except: | |
print(OPCION_INVALIDA) | |
continue | |
# Nuevo Juego o Cargar partida | |
# Nuevo Juego: | |
# Nivel de Dificultad: | |
# Fácil, Medio, Difícil | |
# t = Tablero('facil.txt') | |
# t.colocar_ampolleta(1, 6) | |
# t.tablero_completo() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment