Skip to content

Instantly share code, notes, and snippets.

@NekoTashi
Last active November 18, 2016 22:42
Show Gist options
  • Save NekoTashi/22527f101cc73cfac63bb96c0ded1b4e to your computer and use it in GitHub Desktop.
Save NekoTashi/22527f101cc73cfac63bb96c0ded1b4e to your computer and use it in GitHub Desktop.
Tablero.
-,-,-,-,-,*,-
-,X,X,*,-,1,-
-,-,*,4,*,X,-
-,*,X,*,3,*,-
-,X,-,1,-,-,-
-,2,-,-,1,X,-
-,-,-,-,*,-,-
- http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python
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