Python Tkinter Sockets License

๐Ÿ’ฃ Minesweeper Multiplayer + Dashboard

Un proyecto completo de programaciรณn de servicios y procesos
Juego de buscaminas competitivo en red + Panel de control integral

Caracterรญsticas โ€ข Arquitectura โ€ข Instalaciรณn โ€ข Uso โ€ข Mecรกnicas โ€ข Tecnologรญas

--- ## ๐Ÿ“ธ Vista Previa ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๐ŸŽฎ MINESWEEPER MULTIPLAYER DASHBOARD โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ ACCIONES โ”‚ รREA DE RESULTADOS โ”‚ โ”‚ ๐Ÿ’ฃ MINESWEEPER โ”‚ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”‚ MULTIPLAYER โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ > Wallapop โ”‚ โ”‚ ๐Ÿ“Š Monitor Sistema โ”‚ โ”‚ โ”‚ Ronda: 3 โ”‚ โ”‚ โ”‚ > Scraping โ”‚ โ”‚ ๐Ÿ“ˆ CPU: 45% โ”‚ โ”‚ โ”‚ ๐Ÿ’ฃ Bombas: 9 โ”‚ โ”‚ โ”‚ > API Tiempo โ”‚ โ”‚ ๐Ÿ’พ RAM: 2.1GB โ”‚ โ”‚ โ”‚ โค๏ธ Vidas: 2 โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ APPS โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ Tabs: [Resultados][Navegador] โ”‚ โ”‚ โ”‚ โ–ข โ”‚ โ–ข โ”‚ โœ“ โ”‚ โ”‚ โ”‚ โ”‚ > VS Code โ”‚ [Correos][Bloc][Tareas] โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ > Camellos โ”‚ [Alarmas][Enlaces] โ”‚ โ”‚ โ”‚ ๐Ÿ’ฅโ”‚ โ–ข โ”‚ โ–ข โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ BATCH โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ ๐Ÿ“ Panel de Notas โ”‚ โ”‚ โ”‚ [Iniciar Juego] โ”‚ โ”‚ โ”‚ > Backups โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ [Zona Despejada]โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ## โœจ Caracterรญsticas ### ๐ŸŽฎ **Juego Minesweeper Multijugador** | Caracterรญstica | Descripciรณn | |----------------|-------------| | ๐Ÿ”ฅ **Competitivo** | 2+ jugadores compiten en tiempo real | | ๐Ÿ’ฃ **Colocaciรณn estratรฉgica** | Cada jugador coloca bombas para el rival | | ๐Ÿ”„ **Por turnos** | Sistema de turnos para colocar y buscar | | ๐Ÿ“ˆ **Dificultad progresiva** | 5 rondas con grids y bombas crecientes | | โค๏ธ **Sistema de vidas** | 3 vidas por partida, ยกno las pierdas! | ### ๐Ÿ“Š **Dashboard Integral** - ๐Ÿ“ก **Monitor del sistema** en tiempo real (CPU, RAM, hilos) - ๐ŸŒค๏ธ **API del tiempo** para Jรกvea (OpenWeather) - ๐Ÿ›’ **Anรกlisis de Wallapop** - Scraping de anuncios - โฐ **Sistema de alarmas** programables - ๐Ÿ“ **Bloc de notas** integrado - ๐Ÿ”— **Gestor de enlaces** rรกpidos - ๐ŸŽฒ **Minijuego de camellos** con animaciones --- ## ๐Ÿ—๏ธ Arquitectura ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ARQUITECTURA DEL SISTEMA โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ SERVIDOR TCP โ”‚ โ”‚ servidor.py โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ GameServer โ”‚ โ”‚ โ”‚ โ”‚ - Estado juego โ”‚ โ”‚ โ”‚ โ”‚ - Broadcast โ”‚ โ”‚ โ”‚ โ”‚ - Turnos โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ Puerto 3333 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Protocolo JSON โ”‚ โ”‚ sobre TCP/IP โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ CLIENTE 1 โ”‚ โ”‚ CLIENTE 2 โ”‚ โ”‚ CLIENTE N โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ app.py โ”‚ โ”‚ โ”‚ โ”‚ app.py โ”‚ โ”‚ โ”‚ โ”‚ cliente_ โ”‚ โ”‚ โ”‚ โ”‚ Dashboard โ”‚ โ”‚ โ”‚ โ”‚ Dashboard โ”‚ โ”‚ โ”‚ โ”‚ juego.py โ”‚ โ”‚ โ”‚ โ”‚ + Juego โ”‚ โ”‚ โ”‚ โ”‚ + Juego โ”‚ โ”‚ โ”‚ โ”‚ Standalone โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### ๐Ÿ“ Estructura del Proyecto ``` Proyecto1AVApsp/ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ servidor.py # Servidor TCP del juego (371 lรญneas) โ”‚ โ””โ”€โ”€ GameServer # Gestiona estado, turnos y broadcasts โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ app.py # Dashboard principal (2566 lรญneas) โ”‚ โ”œโ”€โ”€ DashboardApp # Aplicaciรณn Tkinter completa โ”‚ โ””โ”€โ”€ GameClient # Cliente TCP integrado โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ cliente_juego.py # Cliente standalone (220 lรญneas) โ”‚ โ””โ”€โ”€ GameClient # Versiรณn ligera para jugar โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ requirements.txt # Dependencias Python โ””โ”€โ”€ ๐Ÿ“„ README.md # Este archivo ``` --- ## ๐Ÿš€ Instalaciรณn ### Requisitos Previos - **Python 3.8+** - **pip** (gestor de paquetes) ### Paso 1: Clonar el Repositorio ```bash git clone https://github.com/MarcosFerrandiz/Proyecto1AVApsp.git cd Proyecto1AVApsp ``` ### Paso 2: Crear Entorno Virtual (Recomendado) ```bash python -m venv .venv # Linux/macOS source .venv/bin/activate # Windows .venv\Scripts\activate ``` ### Paso 3: Instalar Dependencias ```bash pip install -r requirements.txt ```
๐Ÿ“ฆ Ver dependencias detalladas | Paquete | Versiรณn | Uso | |---------|---------|-----| | `psutil` | โ‰ฅ5.9.0 | Monitor de recursos del sistema | | `matplotlib` | โ‰ฅ3.5.0 | Grรกficos en tiempo real | | `pillow` | โ‰ฅ9.0.0 | Procesamiento de imรกgenes | | `pygame` | โ‰ฅ2.1.0 | Reproducciรณn de audio (opcional) | | `requests` | โ‰ฅ2.32.0 | Peticiones HTTP (API, Scraping) | | `beautifulsoup4` | โ‰ฅ4.12.0 | Parsing HTML (Scraping) |
--- ## ๐ŸŽฏ Uso ### ๐Ÿ–ฅ๏ธ Iniciar el Servidor ```bash python servidor.py ``` > El servidor escucharรก en `0.0.0.0:3333` ### ๐ŸŽฎ Opciรณn A: Dashboard Completo ```bash python app.py ``` Incluye el juego integrado + todas las funcionalidades del panel. ### ๐ŸŽฎ Opciรณn B: Cliente Standalone ```bash python cliente_juego.py ``` Cliente ligero solo para jugar al Minesweeper. ### ๐Ÿ”Œ Conectar al Juego 1. Introduce el **Host** del servidor (por defecto: `127.0.0.1`) 2. Verifica el **Puerto** (por defecto: `3333`) 3. Pulsa **"Conectar"** 4. ยกEspera a otro jugador y pulsa **"Iniciar Juego"**! --- ## ๐Ÿ’ฃ Mecรกnicas del Juego ### ๐Ÿ”„ Flujo de una Partida ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ FLUJO DEL JUEGO โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ LOBBY โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ COLOCACIร“N โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ BรšSQUEDA โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ DE BOMBAS โ”‚ โ”‚ (PLAYING) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ ยฟBOMBA? โ”‚โ”€โ”€โ”€โ–ถโ”‚ EXPLOSIร“Nโ”‚โ”€โ”€โ”€โ–ถโ”‚ ยฟVIDAS=0? โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ NO โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ Sร โ–ผ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ SAFE โ”‚ โ”‚ GAME OVERโ”‚ โ”‚ โ”‚ โ”‚ โ”‚(casilla โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ segura) โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ โ”‚ โ”ฟโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”“ โ”‚ โ”‚ โ”‚ โ”ƒ SIGUIENTE TURNO โ”ƒ โ”‚ โ”‚ โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ (Nueva Partida) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### ๐Ÿ“Š Progresiรณn de Dificultad | Ronda | Tamaรฑo Grid | Bombas/Jugador | Total Bombas* | |:-----:|:-----------:|:--------------:|:-------------:| | 1๏ธโƒฃ | 3ร—3 | 3 | 6 | | 2๏ธโƒฃ | 5ร—5 | 5 | 10 | | 3๏ธโƒฃ | 8ร—8 | 9 | 18 | | 4๏ธโƒฃ | 11ร—11 | 12 | 24 | | 5๏ธโƒฃ+ | 14ร—14 | 15 | 30 | *\*Para 2 jugadores* ### ๐ŸŽฏ Fases del Juego #### 1. ๐Ÿ’ฃ Fase de Colocaciรณn (`PLACING`) - Cada jugador coloca bombas **por turnos** - Las bombas se muestran brevemente (1 segundo) a todos - ยกMemoriza dรณnde pones TUS bombas y las del rival! #### 2. ๐Ÿ” Fase de Bรบsqueda (`PLAYING`) - Excava casillas por turnos - **Casilla segura** โ†’ Se marca en verde โœ… - **Bomba** โ†’ ยกEXPLOSIร“N! Pierdes 1 vida ๐Ÿ’” ### ๐Ÿ† Condiciones de Victoria | Condiciรณn | Resultado | |-----------|-----------| | Rival pierde todas las vidas | **ยกGANASTE!** ๐ŸŽ‰ | | Todas las casillas seguras reveladas | **ยกZona despejada!** | | Superas la ronda 5 | **ยกVictoria total!** ๐Ÿ† | --- ## ๐Ÿ“ก Protocolo de Comunicaciรณn ### Mensajes JSON Cliente โ†’ Servidor ```javascript // Iniciar partida { "type": "START_GAME" } // Colocar bomba (fase PLACING) { "type": "PLACE_BOMB", "x": 2, "y": 1 } // Excavar casilla (fase PLAYING) { "type": "CLICK_CELL", "x": 3, "y": 4 } // Verificar zona despejada { "type": "CHECK_DUNGEON_CLEARED" } ``` ### Mensajes JSON Servidor โ†’ Clientes ```javascript // Nueva ronda { "type": "NEW_ROUND", "round": 1, "grid_size": 3, "total_bombs_per_player": 3 } // Notificaciรณn de turno { "type": "TURN_NOTIFY", "active_player": "('127.0.0.1', 54321)", "msg": "Turno de ... para poner bombas." } // Flash de bomba (visible 1 segundo) { "type": "BOMB_flash", "x": 1, "y": 2, "who": "('127.0.0.1', 54321)" } // Explosiรณn { "type": "EXPLOSION", "x": 1, "y": 2, "who": "...", "lives": 2 } // Casilla segura { "type": "SAFE", "x": 0, "y": 0 } // Game Over { "type": "GAME_OVER", "loser": "...", "msg": "๐Ÿ’€ ยก... ha perdido todas sus vidas!" } ``` --- ## ๐Ÿ”ง Documentaciรณn Tรฉcnica Detallada ### ๐Ÿ†” Sistema de Identificaciรณn de Jugadores El servidor **identifica a cada jugador mediante su direcciรณn de socket**, que es una tupla รบnica `(IP, Puerto)`: ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ IDENTIFICACIร“N รšNICA DE JUGADORES โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Cuando un cliente se conecta al servidor: โ”‚ โ”‚ โ”‚ โ”‚ Cliente 1 โ”€โ”€โ”€โ”€โ”€โ”€โ–บ sock.accept() โ”€โ”€โ”€โ”€โ”€โ”€โ–บ ('127.0.0.1', 49956) โ”‚ โ”‚ Cliente 2 โ”€โ”€โ”€โ”€โ”€โ”€โ–บ sock.accept() โ”€โ”€โ”€โ”€โ”€โ”€โ–บ ('127.0.0.1', 49968) โ”‚ โ”‚ โ”‚ โ”‚ Aunque ambos clientes estรฉn en el MISMO ordenador (127.0.0.1) โ”‚ โ”‚ el PUERTO es diferente y รบnico para cada conexiรณn. โ”‚ โ”‚ โ”‚ โ”‚ Esta tupla (IP, Puerto) actรบa como IDENTIFICADOR รšNICO. โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` #### ยฟCรณmo funciona en el mismo ordenador? ```python # servidor.py - Al aceptar conexiรณn conn, addr = s.accept() # addr = ('127.0.0.1', 49956) # El sistema operativo asigna un puerto efรญmero รšNICO # a cada nueva conexiรณn de socket del cliente ``` | Cliente | IP | Puerto (asignado por SO) | Identificador Completo | |---------|----|--------------------------|-----------------------| | Dashboard 1 | 127.0.0.1 | 49956 | `('127.0.0.1', 49956)` | | Dashboard 2 | 127.0.0.1 | 49968 | `('127.0.0.1', 49968)` | | Cliente remoto | 192.168.1.50 | 52341 | `('192.168.1.50', 52341)` | > **๐Ÿ’ก Clave:** El puerto del cliente es asignado automรกticamente por el sistema operativo y es **siempre diferente** para cada nueva conexiรณn, incluso desde el mismo ordenador. --- ### ๐Ÿ”„ Gestiรณn de Turnos El servidor mantiene **dos รญndices de turno** para controlar quiรฉn juega: ```python # servidor.py - Variables de control de turnos self.placing_turn_index = 0 # รndice en fase PLACING self.playing_turn_index = 0 # รndice en fase PLAYING self.client_list = [] # Lista ordenada de direcciones ``` #### Flujo de Verificaciรณn de Turno ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ VERIFICACIร“N DE TURNO โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ client_list = [('127.0.0.1', 49956), ('127.0.0.1', 49968)] โ”‚ โ”‚ โ†‘ โ†‘ โ”‚ โ”‚ รญndice 0 รญndice 1 โ”‚ โ”‚ โ”‚ โ”‚ Si placing_turn_index = 0: โ”‚ โ”‚ โ†’ Solo ('127.0.0.1', 49956) puede poner bombas โ”‚ โ”‚ โ”‚ โ”‚ Cuando recibe PLACE_BOMB de un cliente: โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ if str(addr) != str(current_turn_addr): โ”‚ โ”‚ โ”‚ โ”‚ return # No es su turno, ignorar โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` #### Cรณdigo de Verificaciรณn (servidor.py) ```python elif msg_type == 'PLACE_BOMB': if self.state == STATE_PLACING: # Obtener quiรฉn tiene el turno actual current_turn_addr = self.client_list[self.placing_turn_index] # Comparar con quiรฉn enviรณ el mensaje if str(addr) != str(current_turn_addr): return # ยกNo es tu turno! Ignorar mensaje # Procesar la bomba... ``` --- ### ๐Ÿ‘ค Cรณmo el Cliente Sabe si es su Turno El cliente guarda su propia direcciรณn al conectarse y la compara con los mensajes del servidor: ```python # app.py - Al conectarse self.my_address = str(sock.getsockname()) # Ej: "('127.0.0.1', 49956)" # Al recibir TURN_NOTIFY del servidor def handle_message(self, msg): if mtype == 'TURN_NOTIFY': active_player = msg.get('active_player') # "('127.0.0.1', 49956)" # Comparar con mi direcciรณn if active_player == self.my_address: self._log_game("๐ŸŽฏ ยกES TU TURNO!") # Habilitar controles... else: self._log_game(f"โณ Turno de {active_player}") # Deshabilitar controles... ``` ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ FLUJO DE NOTIFICACIร“N DE TURNO โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ SERVIDOR CLIENTES โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”‚ โ”‚ broadcast({ Cliente 1 (49956): โ”‚ โ”‚ "type": "TURN_NOTIFY", โ”œโ”€ my_address = 49956 โ”‚ โ”‚ "active_player": โ”œโ”€ active_player = 49956 โ”‚ โ”‚ "('127.0.0.1', 49956)" โ””โ”€ โœ“ ยกES MI TURNO! โ”‚ โ”‚ }) โ”‚ โ”‚ โ”‚ Cliente 2 (49968): โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ โ”œโ”€ my_address = 49968 โ”‚ โ”‚ โ”œโ”€ active_player = 49956 โ”‚ โ”‚ โ””โ”€ โœ— No es mi turno โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ### ๐Ÿ”’ Sincronizaciรณn con Threading Lock El servidor usa un `threading.Lock` para evitar condiciones de carrera cuando mรบltiples clientes envรญan mensajes simultรกneamente: ```python class GameServer: def __init__(self): self.lock = threading.Lock() # Mutex para sincronizaciรณn self.clients = {} # Diccionario compartido self.state = STATE_LOBBY # Estado compartido def process_message(self, client, addr, msg): with self.lock: # Adquirir lock antes de modificar estado if msg_type == 'PLACE_BOMB': # Solo un hilo puede ejecutar esto a la vez self.bombs.add((x, y)) self._broadcast_unlocked(...) ``` ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ SINCRONIZACIร“N CON LOCK โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Hilo Cliente 1 โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”œโ”€โ”€โ–บ with self.lock: โ”€โ”€โ–บ Ejecuta primero โ”‚ โ”‚ Hilo Cliente 2 โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ (espera...) โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ Hilo 2 ejecuta despuรฉs โ”‚ โ”‚ โ”‚ โ”‚ Esto evita que dos jugadores modifiquen el estado โ”‚ โ”‚ del juego al mismo tiempo (condiciones de carrera). โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ### ๐Ÿ“ก Arquitectura de Hilos ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ARQUITECTURA DE HILOS โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ SERVIDOR (servidor.py) โ”‚ โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Hilo Main โ”‚ โ—„โ”€โ”€ Acepta conexiones (s.accept()) โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€โ–บ Hilo Cliente 1 โ”€โ”€โ–บ handle_client(sock1) โ”‚ โ”‚ โ”œโ”€โ”€โ–บ Hilo Cliente 2 โ”€โ”€โ–บ handle_client(sock2) โ”‚ โ”‚ โ””โ”€โ”€โ–บ Hilo Cliente N โ”€โ”€โ–บ handle_client(sockN) โ”‚ โ”‚ โ”‚ โ”‚ Cada cliente tiene su propio hilo daemon que: โ”‚ โ”‚ 1. Lee mensajes del socket (recv) โ”‚ โ”‚ 2. Procesa el mensaje (process_message) โ”‚ โ”‚ 3. Puede hacer broadcast a todos los clientes โ”‚ โ”‚ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”‚ โ”‚ CLIENTE (app.py) โ”‚ โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Hilo Main โ”‚ โ”‚ Hilo Recv โ”‚ โ”‚ โ”‚ โ”‚ (Tkinter UI) โ”‚โ—„โ”€โ”€โ”€โ”‚ (_recv_loop) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ–ฒ โ”‚ โ”‚ โ”‚ msg_queue.put() โ”‚ sock.recv() โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ Cola de msgs โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ (thread-safe) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ El hilo de recepciรณn pone mensajes en una cola. โ”‚ โ”‚ El hilo principal (UI) los procesa con after(). โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ### ๐ŸŽฎ Resumen: Jugar en el Mismo Ordenador | Paso | Quรฉ Sucede | |------|------------| | 1. Iniciar servidor | `python servidor.py` escucha en puerto 3333 | | 2. Abrir Cliente 1 | Conecta โ†’ SO asigna puerto 49956 | | 3. Abrir Cliente 2 | Conecta โ†’ SO asigna puerto 49968 | | 4. Servidor registra | `clients = {sock1: ('127.0.0.1', 49956), sock2: ('127.0.0.1', 49968)}` | | 5. Iniciar juego | `client_list = [addr1, addr2]` define orden de turnos | | 6. Turno jugador 1 | Servidor envรญa `TURN_NOTIFY` con `active_player = addr1` | | 7. Cliente 1 compara | `my_address == active_player` โ†’ ยกEs mi turno! | | 8. Cliente 2 compara | `my_address != active_player` โ†’ Esperar | | 9. Jugador 1 actรบa | Envรญa `PLACE_BOMB` o `CLICK_CELL` | | 10. Servidor valida | `addr == current_turn_addr` โ†’ Vรกlido, procesar | | 11. Avanzar turno | `placing_turn_index += 1` โ†’ Turno del siguiente | --- ## ๐Ÿ› ๏ธ Tecnologรญas
Python
Python 3
Lenguaje base
Tkinter
Tkinter
Interfaz grรกfica
Sockets
TCP Sockets
Comunicaciรณn en red
Matplotlib
Matplotlib
Grรกficos
JSON
JSON
Protocolo mensajes
Requests
Requests
APIs HTTP
### ๐Ÿงต Conceptos de PSP Aplicados | Concepto | Implementaciรณn | |----------|----------------| | **Procesos** | Lanzamiento de aplicaciones externas (VS Code, Firefox) | | **Threads** | Servidor multihilo, cliente con hilos de recepciรณn | | **Sockets TCP** | Comunicaciรณn cliente-servidor en red | | **Servicios** | API OpenWeather, scraping de Wallapop | | **Sincronizaciรณn** | Locks para acceso concurrente a estado compartido | --- ## ๐ŸŽจ Caracterรญsticas del Dashboard ### ๐Ÿ“Š Monitor del Sistema - Grรกfico de CPU en lรญnea temporal - Grรกfico de memoria como รกrea - Contador de hilos del proceso ### ๐ŸŒค๏ธ API del Tiempo (Jรกvea) - Temperatura actual y sensaciรณn tรฉrmica - Humedad y velocidad del viento - Descripciรณn del clima ### ๐Ÿ›’ Anรกlisis Wallapop - Extracciรณn de informaciรณn de anuncios - Headers personalizados para API - Resultados formateados ### โฐ Sistema de Alarmas - Programaciรณn en minutos - Notificaciones visuales - Gestiรณn de alarmas activas --- ## ๐Ÿค Contribuir 1. **Fork** del proyecto 2. Crea tu **Feature Branch** (`git checkout -b feature/NuevaFuncion`) 3. **Commit** tus cambios (`git commit -m 'Add: Nueva funciรณn'`) 4. **Push** a la rama (`git push origin feature/NuevaFuncion`) 5. Abre un **Pull Request** --- ## ๐Ÿ“ Licencia Este proyecto es de carรกcter **educativo** y fue desarrollado como parte del mรณdulo de **Programaciรณn de Servicios y Procesos**. ---

Desarrollado con โค๏ธ por Marcos Ferrandiz

Proyecto 1ยบ Evaluaciรณn - PSP (Programaciรณn de Servicios y Procesos)

---

Estado Versiรณn Python