# ================================================
# PRÁCTICA 9 - JUEGO DE 21 (BLACK JACK) - PICO W
# Modo Estación (Station) - Equipo impar (según tu petición)
# Autor: Generado para tu equipo
# ================================================
import network
import socket
import random
import utime
import ujson
import uasyncio as asyncio
from machine import Pin, I2C
# ==================== CONFIGURACIÓN WIFI ====================
ssid = 'TU_RED_WIFI' # ← CAMBIA ESTO
password = 'TU_CONTRASEÑA' # ← CAMBIA ESTO
# ==================== CONEXIONES (para Wokwi y hardware real) ====================
# LCD I2C 16x2 (dirección común 0x27)
# SDA → GP0
# SCL → GP1
# VCC → 3.3V GND → GND
# Botones (con pull-up interno, conectados a GND)
P1_ASK = Pin(14, Pin.IN, Pin.PULL_UP) # Jugador 1 - Pedir carta
P1_STOP = Pin(15, Pin.IN, Pin.PULL_UP) # Jugador 1 - Detenerse
P2_ASK = Pin(16, Pin.IN, Pin.PULL_UP) # Jugador 2 - Pedir carta
P2_STOP = Pin(17, Pin.IN, Pin.PULL_UP) # Jugador 2 - Detenerse
# ==================== VARIABLES GLOBALES DEL JUEGO ====================
sum1 = 0
sum2 = 0
stopped1 = False
stopped2 = False
current_state = "Listo para iniciar"
# ==================== DRIVER LCD 16x2 I2C (completo y funcional) ====================
class LCD1602:
def __init__(self, i2c, addr=0x27):
self.i2c = i2c
self.addr = addr
self.backlight = 0x08
self.init_lcd()
def send(self, data, mode=0):
high = mode | (data & 0xF0) | self.backlight
low = mode | ((data << 4) & 0xF0) | self.backlight
self.i2c.writeto(self.addr, bytes([high, high | 0x04, high & ~0x04]))
utime.sleep_ms(1)
self.i2c.writeto(self.addr, bytes([low, low | 0x04, low & ~0x04]))
utime.sleep_ms(1)
def init_lcd(self):
self.send(0x03)
utime.sleep_ms(5)
self.send(0x03)
utime.sleep_ms(5)
self.send(0x03)
utime.sleep_ms(5)
self.send(0x02)
self.send(0x28) # 4 bits, 2 líneas
self.send(0x0C) # display on
self.send(0x06) # entry mode
self.send(0x01) # clear
utime.sleep_ms(5)
def clear(self):
self.send(0x01)
utime.sleep_ms(2)
def set_cursor(self, col, row):
row_offsets = [0x80, 0xC0]
self.send(row_offsets[row] | col)
def write_string(self, string, col=0, row=0):
self.set_cursor(col, row)
for char in string:
self.send(ord(char), 1) # modo datos
# Crear objeto LCD
i2c = I2C(0, sda=Pin(0), scl=Pin(1))
lcd = LCD1602(i2c)
# ==================== FUNCIONES DEL JUEGO ====================
def update_lcd():
global current_state
lcd.clear()
lcd.write_string(f"J1:{sum1} J2:{sum2}", 0, 0)
if stopped1 and stopped2:
lcd.write_string(current_state[:16], 0, 1)
else:
lcd.write_string(current_state[:16], 0, 1)
def determine_winner():
global current_state
if sum1 > 21 and sum2 > 21:
current_state = "La casa gana"
elif sum1 == sum2:
current_state = "La casa gana"
elif sum1 > 21:
current_state = "Gana el jugador 2"
elif sum2 > 21:
current_state = "Gana el jugador 1"
else:
# Ambos <= 21 → quien se acerca más a 21
if abs(21 - sum1) < abs(21 - sum2):
current_state = "Gana el jugador 1"
elif abs(21 - sum2) < abs(21 - sum1):
current_state = "Gana el jugador 2"
else:
current_state = "La casa gana"
return current_state
def reset_game():
global sum1, sum2, stopped1, stopped2, current_state
sum1 = 0
sum2 = 0
stopped1 = False
stopped2 = False
current_state = "Listo para iniciar"
update_lcd()
def add_card(player):
global sum1, sum2, current_state
if player == 1 and not stopped1:
sum1 += random.randint(1, 10)
if current_state == "Listo para iniciar":
current_state = "Juego Activo"
elif player == 2 and not stopped2:
sum2 += random.randint(1, 10)
if current_state == "Listo para iniciar":
current_state = "Juego Activo"
update_lcd()
def stop_player(player):
global stopped1, stopped2, current_state
if player == 1 and not stopped1:
stopped1 = True
elif player == 2 and not stopped2:
stopped2 = True
if stopped1 and stopped2:
determine_winner()
update_lcd()
# ==================== MONITOREO DE BOTONES (tarea asíncrona) ====================
async def button_monitor():
last_time = {"p1a": 0, "p1s": 0, "p2a": 0, "p2s": 0}
while True:
now = utime.ticks_ms()
# Jugador 1 - Pedir
if P1_ASK.value() == 0 and now - last_time["p1a"] > 300:
last_time["p1a"] = now
add_card(1)
# Jugador 1 - Detener
if P1_STOP.value() == 0 and now - last_time["p1s"] > 300:
last_time["p1s"] = now
stop_player(1)
# Jugador 2 - Pedir
if P2_ASK.value() == 0 and now - last_time["p2a"] > 300:
last_time["p2a"] = now
add_card(2)
# Jugador 2 - Detener
if P2_STOP.value() == 0 and now - last_time["p2s"] > 300:
last_time["p2s"] = now
stop_player(2)
await asyncio.sleep_ms(50)
# ==================== SERVIDOR WEB ASÍNCRONO ====================
html_page = """[AQUÍ VA TODO EL CÓDIGO HTML QUE TE DI ARRIBA - COPIA Y PEGA COMPLETO]"""
async def handle_client(reader, writer):
try:
request = await reader.read(1024)
request = request.decode('utf-8')
path = request.split(' ')[1]
if path == '/' or path == '/index.html':
await writer.awrite(b'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n')
await writer.awrite(html_page.encode())
elif path == '/status':
data = {
"p1_sum": sum1,
"p2_sum": sum2,
"state": current_state
}
json_str = ujson.dumps(data)
await writer.awrite(b'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n')
await writer.awrite(json_str.encode())
elif path == '/restart':
reset_game()
await writer.awrite(b'HTTP/1.1 302 Found\r\nLocation: /\r\n\r\n')
else:
await writer.awrite(b'HTTP/1.1 404 Not Found\r\n\r\n')
except:
pass
finally:
await writer.aclose()
# ==================== CONEXIÓN WIFI Y EJECUCIÓN PRINCIPAL ====================
print("Conectando a WiFi...")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
while not wlan.isconnected():
utime.sleep(1)
print("✅ Conectado! IP:", wlan.ifconfig()[0])
# Mensaje inicial en LCD
lcd.clear()
lcd.write_string("Bienvenido al", 0, 0)
lcd.write_string("Juego de 21", 0, 1)
utime.sleep(2)
update_lcd()
# ==================== INICIO DE TAREAS ASÍNCRONAS ====================
async def main():
asyncio.create_task(button_monitor())
await asyncio.start_server(handle_client, "0.0.0.0", 80)
while True:
await asyncio.sleep(3600) # mantiene el servidor vivo
asyncio.run(main())