448 lines
19 KiB
Markdown
448 lines
19 KiB
Markdown
<p align="center">
|
||
<img src="https://img.shields.io/badge/Python-3.8+-blue?style=for-the-badge&logo=python&logoColor=white" alt="Python">
|
||
<img src="https://img.shields.io/badge/Tkinter-GUI-green?style=for-the-badge&logo=python&logoColor=white" alt="Tkinter">
|
||
<img src="https://img.shields.io/badge/TCP/IP-Multiplayer-orange?style=for-the-badge&logo=socketdotio&logoColor=white" alt="Sockets">
|
||
<img src="https://img.shields.io/badge/License-Educational-purple?style=for-the-badge" alt="License">
|
||
</p>
|
||
|
||
<h1 align="center">💣 Minesweeper Multiplayer + Dashboard</h1>
|
||
|
||
<p align="center">
|
||
<strong>Un proyecto completo de programación de servicios y procesos</strong><br>
|
||
<em>Juego de buscaminas competitivo en red + Panel de control integral</em>
|
||
</p>
|
||
|
||
<p align="center">
|
||
<a href="#-características">Características</a> •
|
||
<a href="#-arquitectura">Arquitectura</a> •
|
||
<a href="#-instalación">Instalación</a> •
|
||
<a href="#-uso">Uso</a> •
|
||
<a href="#-mecánicas-del-juego">Mecánicas</a> •
|
||
<a href="#-tecnologías">Tecnologías</a>
|
||
</p>
|
||
|
||
---
|
||
|
||
## 📸 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
|
||
```
|
||
|
||
<details>
|
||
<summary>📦 <strong>Ver dependencias detalladas</strong></summary>
|
||
|
||
| 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) |
|
||
|
||
</details>
|
||
|
||
---
|
||
|
||
## 🎯 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!"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ Tecnologías
|
||
|
||
<table>
|
||
<tr>
|
||
<td align="center" width="150">
|
||
<img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/python/python-original.svg" width="48" height="48" alt="Python" />
|
||
<br><strong>Python 3</strong>
|
||
<br><em>Lenguaje base</em>
|
||
</td>
|
||
<td align="center" width="150">
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Virtualbox_logo.png/64px-Virtualbox_logo.png" width="48" height="48" alt="Tkinter" />
|
||
<br><strong>Tkinter</strong>
|
||
<br><em>Interfaz gráfica</em>
|
||
</td>
|
||
<td align="center" width="150">
|
||
<img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/socketio/socketio-original.svg" width="48" height="48" alt="Sockets" />
|
||
<br><strong>TCP Sockets</strong>
|
||
<br><em>Comunicación en red</em>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="center">
|
||
<img src="https://matplotlib.org/stable/_static/logo_light.svg" width="48" height="48" alt="Matplotlib" />
|
||
<br><strong>Matplotlib</strong>
|
||
<br><em>Gráficos</em>
|
||
</td>
|
||
<td align="center">
|
||
<img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/json/json-original.svg" width="48" height="48" alt="JSON" />
|
||
<br><strong>JSON</strong>
|
||
<br><em>Protocolo mensajes</em>
|
||
</td>
|
||
<td align="center">
|
||
<img src="https://www.vectorlogo.zone/logos/pocoo_flask/pocoo_flask-icon.svg" width="48" height="48" alt="Requests" />
|
||
<br><strong>Requests</strong>
|
||
<br><em>APIs HTTP</em>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
### 🧵 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**.
|
||
|
||
---
|
||
|
||
<p align="center">
|
||
<strong>Desarrollado con ❤️ por Marcos Ferrandiz</strong>
|
||
</p>
|
||
|
||
<p align="center">
|
||
<em>Proyecto 1º Evaluación - PSP (Programación de Servicios y Procesos)</em>
|
||
</p>
|
||
|
||
---
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/Estado-Completado-success?style=flat-square" alt="Estado">
|
||
<img src="https://img.shields.io/badge/Versión-1.0-blue?style=flat-square" alt="Versión">
|
||
<img src="https://img.shields.io/badge/Made%20with-Python-yellow?style=flat-square&logo=python" alt="Python">
|
||
</p>
|