Juego de laberintos generados proceduralmente con algoritmo DFS modificado
- Descripcion
- Caracteristicas
- Instalacion
- Ejecucion
- Como Jugar
- Niveles de Dificultad
- Arquitectura
- Algoritmo de Generacion
- Estructura del Proyecto
- API Reference
- Tests
- Contribuir
- Changelog
- Licencia
Generador de laberintos es un juego desarrollado en Python que crea laberintos unicos en cada partida mediante generacion procedural. El jugador debe navegar desde el punto de inicio hasta la meta antes de que se agote el tiempo.
- Educativo: Implementacion practica de algoritmos de grafos (DFS, BFS)
- Modular: Arquitectura limpia siguiendo principios SOLID
- Documentado: Codigo exhaustivamente comentado para la comunidad dev
- Testeado: 91 tests unitarios con pytest
| Caracteristica | Descripcion |
|---|---|
| Generacion Procedural | Algoritmo DFS modificado que garantiza laberintos siempre resolubles |
| 5 Niveles de Dificultad | Desde 15x15 hasta 55x55 celdas con complejidad progresiva |
| Sistema de Camara | Seguimiento suave del jugador con interpolacion lineal |
| Indicador de Meta | Flecha direccional cuando la meta no es visible |
| Pausa | Sistema de pausa con tecla P que congela el temporizador |
| Responsive | Tamano de celda dinamico que se adapta a cualquier dificultad |
- Python 3.8 o superior
- pip (gestor de paquetes de Python)
- Git
# Clonar el repositorio
git clone https://github.com/686f6c61/generador-laberintos-python.git
cd generador-laberintos-python
# Opcion 1: Ejecutar directamente (crea entorno virtual automaticamente)
./run.sh
# Opcion 2: Instalacion manual
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtpygame>=2.5.0 # Motor grafico y manejo de eventos
numpy>=1.24.0 # Matrices optimizadas para el laberinto# Metodo recomendado (gestiona entorno virtual automaticamente)
./run.sh
# Ejecucion directa
python3 src/main.py
# Ejecutar tests
python3 -m pytest tests/ -v| Tecla | Accion |
|---|---|
↑ ↓ ← → |
Mover personaje |
P |
Pausar / Reanudar |
Boton Menu |
Volver al menu principal |
- Inicio: Circulo rojo - punto de partida
- Meta: Circulo verde - destino final
- Jugador: Circulo azul - tu personaje
- Llega a la meta antes de que el tiempo se agote
┌─────────────────────────────────────────┐
│ Tiempo: 00:45 Distancia: 12 celdas │ ← Panel Superior
├─────────────────────────────────────────┤
│ │
│ ████████████████ │
│ █ █ │
│ █ ██████ ██ █ │
│ █ █ █ █ █ │
│ █ █ ● ████ █ │ ← Area de Juego
│ █ █ █ █ │
│ █ ███████████ █ │
│ █ █ │
│ ████████████████ │
│ │
├─────────────────────────────────────────┤
│ [Menu] v0.2 686f6c61 │ ← Panel Inferior
└─────────────────────────────────────────┘
| Nivel | Tamano | Celdas | Complejidad | Densidad | Tiempo |
|---|---|---|---|---|---|
| Facil | 15×15 | 225 | 0.5 | 0.5 | 2 min |
| Normal | 25×25 | 625 | 0.6 | 0.6 | 3 min |
| Dificil | 35×35 | 1,225 | 0.7 | 0.7 | 4 min |
| Muy Dificil | 45×45 | 2,025 | 0.8 | 0.8 | 5 min |
| Extremo | 55×55 | 3,025 | 0.9 | 0.9 | 6 min |
Nota: El tamano de celda se calcula dinamicamente para que el laberinto siempre quepa en la ventana (800x600 - paneles HUD).
graph TB
subgraph "Capa de Presentacion"
A[main.py<br/>Punto de entrada]
B[pantalla.py<br/>Renderizado UI]
end
subgraph "Capa de Logica"
C[laberinto.py<br/>Generacion DFS]
D[personaje.py<br/>Control jugador]
end
subgraph "Capa de Datos"
E[config.py<br/>Configuracion]
F[helpers.py<br/>Utilidades]
end
A --> B
A --> C
A --> D
B --> C
B --> D
B --> F
C --> E
C --> F
D --> C
D --> E
D --> F
stateDiagram-v2
[*] --> MENU_PRINCIPAL
MENU_PRINCIPAL --> DIFICULTAD: Seleccionar dificultad
MENU_PRINCIPAL --> JUGANDO: Jugar
MENU_PRINCIPAL --> [*]: Salir
DIFICULTAD --> MENU_PRINCIPAL: Volver / Seleccionar
JUGANDO --> PAUSADO: Tecla P
JUGANDO --> MENU_PRINCIPAL: Boton Menu
JUGANDO --> VICTORIA: Llegar a meta
JUGANDO --> DERROTA: Tiempo agotado
PAUSADO --> JUGANDO: Tecla P
VICTORIA --> MENU_PRINCIPAL: Volver
DERROTA --> MENU_PRINCIPAL: Volver
flowchart LR
A[Eventos] --> B[Actualizar]
B --> C[Renderizar]
C --> D[Display Flip]
D --> E[Tick 60 FPS]
E --> A
El laberinto se genera usando Depth-First Search con modificaciones para crear laberintos mas interesantes:
flowchart TD
A[Iniciar matriz<br/>llena de paredes] --> B[Elegir celda inicial<br/>aleatoria]
B --> C[Marcar como visitada]
C --> D{Hay vecinos<br/>no visitados?}
D -->|Si| E[Elegir vecino aleatorio]
E --> F[Derribar pared entre celdas]
F --> G[Push a pila]
G --> C
D -->|No| H{Pila vacia?}
H -->|No| I[Pop de pila]
I --> C
H -->|Si| J[Agregar bifurcaciones<br/>segun complejidad]
J --> K[Crear ciclos<br/>segun densidad]
K --> L[Verificar solvibilidad<br/>con BFS]
L --> M[Laberinto completo]
# Matriz NumPy optimizada (uint8 = 8x menos memoria que int64)
self.matriz = np.zeros((filas, columnas), dtype=np.uint8)
# Valores de celda
0 = Camino (transitable)
1 = Pared (bloqueada)| Parametro | Rango | Efecto |
|---|---|---|
complejidad |
0.0 - 1.0 | Cantidad de bifurcaciones y caminos alternativos |
densidad |
0.0 - 1.0 | Cantidad de paredes adicionales y callejones sin salida |
generador-laberintos-python/
│
├── src/ # Codigo fuente principal
│ ├── main.py # Punto de entrada, game loop
│ │
│ ├── configuracion/
│ │ ├── __init__.py
│ │ └── config.py # Constantes, colores, dificultades
│ │
│ ├── generador/
│ │ ├── __init__.py
│ │ └── laberinto.py # Clase Laberinto, algoritmo DFS
│ │
│ ├── jugador/
│ │ ├── __init__.py
│ │ └── personaje.py # Clase Jugador, movimiento, colisiones
│ │
│ ├── renderizador/
│ │ ├── __init__.py
│ │ └── pantalla.py # Menus, HUD, PantallaJuego
│ │
│ └── utilidades/
│ ├── __init__.py
│ └── helpers.py # Temporizador, funciones auxiliares
│
├── tests/ # Tests unitarios (91 tests)
│ ├── __init__.py
│ ├── test_config.py # Tests de configuracion
│ ├── test_helpers.py # Tests de utilidades
│ └── test_laberinto.py # Tests de generacion
│
├── assets/ # Recursos graficos
│ └── laberinto.png
│
├── requirements.txt # Dependencias Python
├── run.sh # Script de ejecucion
├── LICENSE # Licencia MIT
└── README.md # Este archivo
from generador.laberinto import Laberinto
# Crear laberinto personalizado
laberinto = Laberinto(
filas=25, # Numero de filas
columnas=25, # Numero de columnas
complejidad=0.6, # Factor de complejidad (0-1)
densidad=0.6, # Factor de densidad (0-1)
tamano_celda=30 # Pixeles por celda (opcional)
)
# Propiedades
laberinto.inicio # Tupla (fila, columna) del inicio
laberinto.meta # Tupla (fila, columna) de la meta
laberinto.matriz # Matriz NumPy del laberinto
laberinto.ancho # Ancho total en pixeles
laberinto.alto # Alto total en pixeles
# Metodos
laberinto.es_pared(fila, columna) # bool: Es pared?
laberinto.es_meta(fila, columna) # bool: Es la meta?
laberinto.dibujar(superficie) # Renderizar en pygame.Surfacefrom jugador.personaje import Jugador
jugador = Jugador(laberinto)
# Propiedades
jugador.posicion # Tupla (x, y) en pixeles
jugador.celda # Tupla (fila, columna)
# Metodos
jugador.manejar_evento(evento) # Procesar input
jugador.actualizar() # Actualizar posicion
jugador.dibujar(superficie) # Renderizar
jugador.reiniciar() # Volver al inicio
jugador.ha_llegado_meta() # bool: Victoria?from utilidades.helpers import Temporizador
temp = Temporizador(tiempo_limite=180) # 3 minutos
temp.obtener_tiempo_transcurrido() # Segundos jugados
temp.obtener_tiempo_restante() # Segundos restantes (o None)
temp.ha_terminado() # bool: Tiempo agotado?
temp.pausar() # Pausar contador
temp.reanudar() # Reanudar contador
temp.reiniciar(nuevo_limite) # Reiniciar con nuevo tiempo# Todos los tests
python3 -m pytest tests/ -v
# Con cobertura
python3 -m pytest tests/ --cov=src --cov-report=html
# Tests especificos
python3 -m pytest tests/test_laberinto.py -v
python3 -m pytest tests/test_helpers.py -v
python3 -m pytest tests/test_config.py -v| Modulo | Tests | Cobertura |
|---|---|---|
config.py |
34 | Configuracion, colores, dificultades |
helpers.py |
26 | Temporizador, formateo, interpolacion |
laberinto.py |
31 | Generacion, solvibilidad, metodos |
| Total | 91 | 100% passed |
def test_laberinto_tiene_solucion():
"""Verificar que todo laberinto generado es resoluble."""
for _ in range(10):
laberinto = Laberinto(25, 25, 0.7, 0.7)
assert laberinto._hay_camino(laberinto.inicio, laberinto.meta)- Fork del repositorio
- Crear branch para tu feature (
git checkout -b feature/nueva-funcionalidad) - Commit de cambios (
git commit -m 'Add: nueva funcionalidad') - Push al branch (
git push origin feature/nueva-funcionalidad) - Abrir Pull Request
- Seguir PEP 8 para codigo Python
- Docstrings en formato Google para todas las funciones publicas
- Tests unitarios para nuevas funcionalidades
- Commits en formato:
Add:,Fix:,Update:,Remove:
Nuevas Caracteristicas
- Sistema de pausa con tecla P
- Tamano de celda dinamico segun dificultad
- 91 tests unitarios con pytest
- Documentacion exhaustiva del codigo
Mejoras
- Optimizacion de memoria: matriz uint8 (8x menos memoria)
- Cache de fuentes para mejor rendimiento
- Estados del juego con Enum (type-safe)
- Constantes extraidas a configuracion
Correcciones
- HUD ya no se superpone al laberinto
- Laberinto siempre cabe en la ventana
- Indicador de meta respeta los paneles
- Lanzamiento inicial
- Generacion de laberintos con DFS
- 5 niveles de dificultad
- Interfaz grafica con Pygame
Este proyecto esta disponible bajo la licencia MIT para uso educativo y personal.
MIT License
Copyright (c) 2025 686f6c61
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software...
Desarrollado con ❤️ por 686f6c61
Si este proyecto te resulta util, considera darle una ⭐
