Desarrollando una Biblioteca de Lógica para el Juego de Batalla Naval en Python: Arquitectura y Errores Comunes
La biblioteca implementa la lógica del clásico juego de Batalla Naval con un enfoque en algoritmos matemáticamente óptimos. Las clases principales son Campo para representar el tablero de juego y Barco para gestionar los barcos. El campo se almacena como una matriz de 10x10 usando listas de listas, donde los símbolos denotan estados: espacio para una celda vacía, '1' para una parte de barco intacta, '.' para un fallo, 'X' para una celda destruida.
La clase Campo maneja la creación del tablero, validación de coordenadas, colocación de barcos y procesamiento de disparos. Las coordenadas se ingresan en el formato 'a1', donde las letras A-J corresponden a filas y los números 1-10 a columnas. Las reglas son fijas: 1 barco de cuatro celdas, 2 barcos de tres celdas, 3 barcos de dos celdas, 4 barcos de una celda; los barcos no deben tocarse entre sí, ni siquiera en las esquinas.
Implementando la Clase Campo
La inicialización crea una cuadrícula vacía:
class Campo:
def __init__(self):
altura = 10
ancho = 10
self.cuadricula = [[' ' for i in range(ancho)] for i in range(altura)]
El método mostrar() imprime el campo en la consola con coordenadas. La primera versión contenía un error: el método line.insert(0, letter) mutaba la cuadrícula original al agregar letras en llamadas repetidas. La solución: imprimir la letra por separado sin alterar la estructura.
def mostrar(self):
print(' 1 2 3 4 5 6 7 8 9 10')
letras = 'ABCDEFGHIJ'
contador_letras = 0
for linea in self.cuadricula:
print(letras[contador_letras], *linea)
contador_letras += 1
La validación de coordenadas se extrae en el método privado _validar_coordenada(). Verifica la longitud de la cadena (2-3 caracteres), presencia de una letra en A-J y un número en 1-10. El método encontrar_coordenada() determina el estado de la celda: libre, golpeada, destruida, no_dañada, ya_golpeada.
Los diccionarios para conversión de coordenadas se almacenan como atributos self.filas y self.columnas:
- filas: {'a': 0, 'b': 1, ..., 'j': 9}
- columnas: {'1': 0, '2': 1, ..., '10': 9}
La Clase Barco y la Colocación de Barcos
La clase Barco almacena parámetros en un diccionario:
class Barco:
def __init__(self):
self.parametros = {
'coordenadas vivas': [],
'coordenadas golpeadas': [],
'vivo': True
}
self.campo = None
def establecer_campo(self, campo):
self.campo = campo
El método agregar_barco(barco, linea_coordenadas, longitud) en Campo coloca un barco basado en una cadena como 'a1-a2-a3'. Primero, validación de línea _validar_linea_barco(): analizar en coordenadas, verificar linealidad (horizontal/vertical) y coincidencia de longitud. Luego, para cada coordenada, llamar barco.establecer_coordenada_en_barco(coordenada), estableciendo '1' en la cuadrícula.
def agregar_barco(self, barco, linea_coordenadas, longitud):
barco.establecer_campo(self)
if not self._validar_linea_barco(linea_coordenadas):
return False
coordenadas = linea_coordenadas.split('-')
if longitud != len(coordenadas):
return False
for coordenada in coordenadas:
resultado = barco.establecer_coordenada_en_barco(coordenada)
if resultado:
filas = self.filas[coordenada[0]]
columnas = self.columnas[coordenada[1:]]
self.cuadricula[filas][columnas] = '1'
return True
La relación Campo-Barco es bidireccional: Campo llama barco.establecer_campo(self), y Barco usa self.campo para validación. Esto viola el principio de encapsulación de capas base pero simplifica la API.
Perspectivas de Refactorización
El proyecto reveló errores clave para principiantes:
- Sobrecarga de Métodos: encontrar_coordenada() combinaba validación, búsqueda y salida—se dividió en _validar_coordenada() y obtener_estado_celda().
- Mutación de Datos: Evitar insert() en mostrar(); trabajar con copias.
- Diccionarios Codificados: Extraer en constantes de clase o usar ord() para conversiones.
- Valores de Retorno: Estandarizar: True/False para éxito, cadenas para errores.
Para un juego óptimo, integrar algoritmos de búsqueda probabilística: al acertar, escanear celdas adyacentes; al destruir, excluir cubiertas de probabilidades.
Conclusiones Clave
- Campo como matriz de listas con símbolos para estados; validación de coordenadas vía diccionarios self.filas/self.columnas.
- Barco almacena coordenadas vivas/golpeadas; enlace bidireccional con Campo vía establecer_campo().
- Colocación vía linea_coordenadas ('a1-a2'); verificar linealidad y zonas de amortiguación.
- Evitar mutar cuadrícula en mostrar(); extraer verificaciones comunes en métodos privados.
- Para algoritmos avanzados: almacenar un mapa de probabilidad de disparos separado de la cuadrícula.
— Editorial Team
Aún no hay comentarios.