import time
import random
from machine import Pin, I2C
# ============================================================
# DRIVER LCD I2C (PCF8574)
# ============================================================
class LCD_I2C:
EN = 0x04
RS = 0x01
BL = 0x08
def __init__(self, i2c, addr=0x27):
self.i2c = i2c
self.addr = addr
self._bl = self.BL
time.sleep_ms(50)
for _ in range(3):
self._w4(0x03)
time.sleep_ms(5)
self._w4(0x02)
self._cmd(0x28)
self._cmd(0x0C)
self._cmd(0x06)
self.clear()
def _byte(self, b):
self.i2c.writeto(self.addr, bytes([b | self._bl]))
def _strobe(self, d):
self._byte(d | self.EN)
time.sleep_us(500)
self._byte(d & ~self.EN)
time.sleep_us(100)
def _w4(self, val):
self._strobe((val << 4))
def _send(self, val, mode):
self._strobe((val & 0xF0) | mode)
self._strobe(((val << 4) & 0xF0) | mode)
def _cmd(self, val): self._send(val, 0)
def _chr(self, val): self._send(val, self.RS)
def clear(self):
self._cmd(0x01)
time.sleep_ms(2)
def set_cursor(self, col, row):
self._cmd(0x80 | ([0x00, 0x40][row] + col))
def print(self, text):
for ch in text:
self._chr(ord(ch))
def print_line(self, row, text):
text = text[:16]
while len(text) < 16:
text = text + " "
self.set_cursor(0, row)
self.print(text)
# ============================================================
# ESTADO DEL JUEGO
# ============================================================
STATUS_READY = "Listo para iniciar"
STATUS_ACTIVE = "Juego Activo"
STATUS_P1 = "Gana el jugador 1"
STATUS_P2 = "Gana el jugador 2"
STATUS_HOUSE = "La casa gana"
scores = [0, 0]
stopped = [False, False]
last_card = [None, None]
status = STATUS_READY
def reset_game():
global scores, stopped, last_card, status
scores = [0, 0]
stopped = [False, False]
last_card = [None, None]
status = STATUS_READY
def add_card(player):
global status
card = random.randint(1, 10)
scores[player] += card
last_card[player] = card
status = STATUS_ACTIVE
return card
def stop_player(player):
stopped[player] = True
check_winner()
def check_winner():
global status
if not (stopped[0] and stopped[1]):
return
s1, s2 = scores
b1, b2 = s1 > 21, s2 > 21
if b1 and b2: status = STATUS_HOUSE
elif b1: status = STATUS_P2
elif b2: status = STATUS_P1
elif s1 == s2: status = STATUS_HOUSE
elif s1 > s2: status = STATUS_P1
else: status = STATUS_P2
def game_over():
return status not in (STATUS_READY, STATUS_ACTIVE)
# ============================================================
# LCD HELPERS
# ============================================================
def lcd_welcome(lcd):
lcd.print_line(0, " BLACKJACK 21 ")
lcd.print_line(1, " Presiona boton ")
def lcd_update(lcd):
s1, s2 = scores
lc1 = f"{last_card[0]:2d}" if last_card[0] else "--"
lc2 = f"{last_card[1]:2d}" if last_card[1] else "--"
if status == STATUS_READY:
lcd_welcome(lcd)
return
lcd.print_line(0, f"J1 C:{lc1} J2 C:{lc2}")
if game_over():
msg = {STATUS_P1:"Gana J1!", STATUS_P2:"Gana J2!", STATUS_HOUSE:"Casa gana"}.get(status,"")
lcd.print_line(1, f"S1={s1} S2={s2} {msg}"[:16])
else:
st1 = "P" if stopped[0] else " "
st2 = "P" if stopped[1] else " "
lcd.print_line(1, f"S1={s1:2d}{st1} S2={s2:2d}{st2} ")
# ============================================================
# MONITOR SERIAL (simula el estado de la web)
# ============================================================
def print_web_status():
print("=" * 36)
print(f" ESTADO : {status}")
print(f" J1 : {scores[0]} pts {'[PLANTADO]' if stopped[0] else ''}")
print(f" J2 : {scores[1]} pts {'[PLANTADO]' if stopped[1] else ''}")
print("=" * 36)
# ============================================================
# DEBOUNCE
# ============================================================
DEBOUNCE_MS = 250
class Button:
def __init__(self, pin_num):
self.pin = Pin(pin_num, Pin.IN, Pin.PULL_UP)
self._last = 0
def pressed(self):
if not self.pin.value():
now = time.ticks_ms()
if time.ticks_diff(now, self._last) > DEBOUNCE_MS:
self._last = now
return True
return False
# ============================================================
# MAIN
# ============================================================
def main():
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400_000)
lcd = LCD_I2C(i2c, addr=0x27)
btn = [
Button(14), # J1 pedir [0]
Button(15), # J1 parar [1]
Button(16), # J2 pedir [2]
Button(17), # J2 parar [3]
]
lcd_welcome(lcd)
print("BlackJack listo. Usa los botones.")
print_web_status()
last_serial = time.ticks_ms()
while True:
if not game_over():
# J1 pedir carta
if btn[0].pressed() and not stopped[0]:
add_card(0)
lcd_update(lcd)
if scores[0] > 21:
stop_player(0)
lcd_update(lcd)
print_web_status()
# J1 plantarse
elif btn[1].pressed() and not stopped[0]:
stop_player(0)
lcd_update(lcd)
print_web_status()
# J2 pedir carta
if btn[2].pressed() and not stopped[1]:
add_card(1)
lcd_update(lcd)
if scores[1] > 21:
stop_player(1)
lcd_update(lcd)
print_web_status()
# J2 plantarse
elif btn[3].pressed() and not stopped[1]:
stop_player(1)
lcd_update(lcd)
print_web_status()
# Imprimir estado cada 2 segundos (simula refresco web)
now = time.ticks_ms()
if time.ticks_diff(now, last_serial) >= 2000:
last_serial = now
print_web_status()
# Si el juego termino, esperar boton J1 Parar para reiniciar
if game_over():
if btn[1].pressed() or btn[3].pressed():
reset_game()
lcd_welcome(lcd)
print("Juego reiniciado.")
print_web_status()
time.sleep_ms(20)
main()