179 lines
6.6 KiB
Python
179 lines
6.6 KiB
Python
import random
|
||
import re
|
||
import os
|
||
|
||
|
||
# Limpiar Pantalla
|
||
cl = lambda: os.system('clear') if os.name == 'posix' else os.system('cls')
|
||
|
||
class Tablero:
|
||
"""
|
||
Creación de objeto tablero que representa al juego 'BuscaMinas'
|
||
"""
|
||
|
||
def __init__(self, dim_size, num_bombs):
|
||
self.dim_size = dim_size
|
||
self.num_bombs = num_bombs
|
||
|
||
# Crear tablero (helper function?)
|
||
self.tablero = self.hacer_nuevo_tablero() # Plantar bombas
|
||
self.asignar_valores_a_tablero()
|
||
|
||
# Inicializar un set() para hacer seguimiento de las locaciones descubiertas
|
||
# se almacenan tuplas (fila, columna) en este set
|
||
self.excavado = set()
|
||
|
||
def hacer_nuevo_tablero(self):
|
||
"""
|
||
Cronstruye un nuevo tablero según dim_size y num_bombs.
|
||
Basado en una lista de listas (represantación 2-D)
|
||
"""
|
||
# generar nuevo tablero
|
||
tablero = [[None for _ in range(self.dim_size)] for _ in range(self.dim_size)]
|
||
# Contruye algo como esto:
|
||
# [ [None, None, .., None],
|
||
# [None, None, .., None],
|
||
# [... ...],
|
||
# [None, None, .., None] ]
|
||
|
||
# Plantar bombas
|
||
bombas_plantadas = 0
|
||
while bombas_plantadas < self.num_bombs:
|
||
loc = random.randint(0, self.dim_size ** 2 - 1)
|
||
fil = loc // self.dim_size
|
||
col = loc % self.dim_size
|
||
|
||
if tablero[fil][col] == '💥️':
|
||
continue # ignorar
|
||
tablero[fil][col] = '💥️' # plantar bomba
|
||
bombas_plantadas += 1
|
||
return tablero
|
||
|
||
def asignar_valores_a_tablero(self):
|
||
"""
|
||
Asigna números enteros de 0 a 8 a cada espacio vacío, según
|
||
cuantas bombas existan al rededor
|
||
"""
|
||
for f in range(self.dim_size):
|
||
for c in range(self.dim_size):
|
||
if self.tablero[f][c] == '💥️':
|
||
continue # si ya es una bomba
|
||
self.tablero[f][c] = self.get_num_bombs_cercanas(f, c)
|
||
|
||
def get_num_bombs_cercanas(self, fil, col):
|
||
"""
|
||
Itera cada cuadrante cercano y suma el número de bombas
|
||
'top left: (fil-1, col-1) top middle: (fil-1, col) top right: (fil-1, col+1)'
|
||
' left: ( fil, col-1) right : ( fil, col+1)'
|
||
'bot left: (fil+1, col-1) bot middle: (fil+1, col) bot right: (fil+1, col+1)'
|
||
"""
|
||
num_bombs_cerca = 0
|
||
for f in range( max(0, fil-1), min(self.dim_size-1, fil+1) +1):
|
||
for c in range( max(0, col-1), min(self.dim_size-1, col+1) +1):
|
||
if f == fil and c == col:
|
||
continue # posicion original, no checkear
|
||
if self.tablero[f][c] == '💥️':
|
||
num_bombs_cerca += 1
|
||
return num_bombs_cerca
|
||
|
||
def excavar(self, fil, col):
|
||
"""
|
||
Busca minas en la posicion, retorna True si tiene exito
|
||
False si es una bomba (gameover), si no hay bombas cercanas
|
||
la busqueda sigue recursivamente
|
||
"""
|
||
self.excavado.add((fil, col)) # seguimiento de locaciones 'excavadas'
|
||
if self.tablero[fil][col] == '💥️':
|
||
return False
|
||
elif self.tablero[fil][col] > 0:
|
||
return True
|
||
|
||
# self.tablero[fil][col] == 0
|
||
for f in range( max(0, fil-1), min(self.dim_size-1, fil+1) +1):
|
||
for c in range( max(0, col-1), min(self.dim_size-1, col+1) +1):
|
||
if (f, c) in self.excavado:
|
||
continue # no 'excava' donde ya se ha 'excavado'
|
||
self.excavar(f, c)
|
||
return True
|
||
|
||
def __str__(self):
|
||
"""
|
||
Retorna un string con la represantación del tablero de juego
|
||
"""
|
||
tablero_visible = [[None for _ in range(self.dim_size) ] for _ in range(self.dim_size)]
|
||
for fil in range(self.dim_size):
|
||
for col in range(self.dim_size):
|
||
if (fil, col) in self.excavado:
|
||
tablero_visible[fil][col] = str(self.tablero[fil][col])
|
||
else:
|
||
tablero_visible[fil][col] = ' '
|
||
# Formato de string para represantación de tablero
|
||
string_rep = ''
|
||
anchos = [] # anchos maximo de columna para print
|
||
for idx in range(self.dim_size):
|
||
columnas = map(lambda x: x[idx], tablero_visible)
|
||
anchos.append(len(max(columnas, key = len)))
|
||
|
||
# print the csv strings
|
||
indices = [i for i in range(self.dim_size)]
|
||
indices_fil = ' '
|
||
cells = []
|
||
for idx, col in enumerate(indices):
|
||
format = '%-' + str(anchos[idx]) + "s"
|
||
cells.append(format % (col))
|
||
indices_fil += ' '.join(cells)
|
||
indices_fil += ' \n'
|
||
|
||
for i in range(len(tablero_visible)):
|
||
fila = tablero_visible[i]
|
||
string_rep += f'{i} |'
|
||
cells = []
|
||
for idx, col in enumerate(fila):
|
||
format = '%-' + str(anchos[idx]) + "s"
|
||
cells.append(format % (col))
|
||
string_rep += ' |'.join(cells)
|
||
string_rep += ' |\n'
|
||
|
||
str_len = int(len(string_rep) / self.dim_size)
|
||
string_rep = indices_fil + '-'*str_len + '\n' + string_rep + '-'*str_len
|
||
|
||
return string_rep
|
||
|
||
def jugar(dim_size = 10, num_bombs = 10):
|
||
"""
|
||
Comenzar juego
|
||
Paso 1 : Crear tablero y plantar bombas
|
||
Paso 2 : Mostrar tablero y preguntar donde excavar
|
||
Paso 3a: Si se elige el lugar donde hay una bomba, muestra Game Over
|
||
Paso 3b: Si el cuadrante no es una bomba, excava recursivamente hasta un cuadrante
|
||
cercano a una bomba.
|
||
Paso 4 : Repetir pasos 2 y 3 hasta que no queden espacios para excavar -> Victoria!
|
||
"""
|
||
# Paso 1
|
||
safe = True
|
||
tablero = Tablero(dim_size ,num_bombs)
|
||
# Paso 2
|
||
while len(tablero.excavado) < tablero.dim_size ** 2 - num_bombs:
|
||
cl()
|
||
print(tablero)
|
||
# 3, 4 o 3, 4 o 3, 4
|
||
user_input = re.split(',(\\s)*', input("Ingresa coordenada para buscar\n-> fila, columna : "))
|
||
fil, col = int(user_input[0]), int(user_input[-1])
|
||
if fil < 0 or fil >= tablero.dim_size or col < 0 or col >= dim_size:
|
||
print("Posición invalida, prueba otra.")
|
||
continue
|
||
# si es valida
|
||
safe = tablero.excavar(fil, col)
|
||
if not safe:
|
||
break # game over
|
||
if safe:
|
||
print("\n 🎉️FELICITACIONES!!🎊️ Ganaste 😎️ ")
|
||
else:
|
||
cl()
|
||
tablero.excavado = [(f, c) for f in range(tablero.dim_size) for c in range(tablero.dim_size)]
|
||
print(tablero)
|
||
print("\n Perdiste! 👻️ \n")
|
||
|
||
if __name__ == '__main__':
|
||
jugar()
|