El taulell de joc és un camp minat i cal detectar on estan totes les mines sense que n'esclati cap. Cada cop que es pica en una casella, si no hi ha cap mina, s'hi indica quantes mines hi ha situades a les caselles del voltant; això permet identificar les posicions de les mines. Es pot posar una bandera en les caselles on se suposa que hi ha una mina, per facilitar la cerca. El botó B serveix per descobrir una casella i el botó A posa una bandera.
Les imatges que es fan servir en el joc (puntero.bmp i Buscaminas.bmp) són les següents:
El programa és el següent:
import board import displayio import ugame import adafruit_imageload import neopixel import random from adafruit_bitmap_font import bitmap_font from adafruit_display_text import label import time
# Crear la pantalla principal
pant = board.DISPLAY
# Carregar les imatges del joc
imatges, palette = adafruit_imageload.load("/Buscaminas.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
# Carregar la imatge del punter
puntero, palette2 = adafruit_imageload.load("/puntero.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
palette2.make_transparent(0) # Fer el color de fons transparent
# Carregar les fonts personalitzades
font = bitmap_font.load_font("/fonts/ic8x16u.bdf")
font2 = bitmap_font.load_font("/fonts/ic16x16u.bdf")
font3 = bitmap_font.load_font("/fonts/ib16x16u.bdf")
# Inicialitzar la cadena de llums LED
cadena = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.3)
def seleccionar_dificultat():
# Crear les etiquetes per al menú de selecció de dificultat
titol = label.Label(font2, text="BUSCAMINES", color=0xFFA500, x=2, y=25)
dificultat_facil = label.Label(font, text=" ? Fàcil", color=0x0000FF, x=13, y=60)
dificultat_dificil = label.Label(font, text=" ? Difícil", color=0x0000FF, x=13, y=90)
# Crear un grup de textos i afegir-hi les etiquetes
grup_text = displayio.Group()
grup_text.append(titol)
grup_text.append(dificultat_facil)
grup_text.append(dificultat_dificil)
while True:
pant.show(grup_text) # Mostrar les opcions de dificultat
boto = ugame.buttons.get_pressed()
if boto & ugame.K_DOWN:
return "Dificil" # Retornar "Difícil" si es prem la fletxa avall
elif boto & ugame.K_UP:
return "Facil" # Retornar "Fàcil" si es prem la fletxa amunt
def iniciar_joc(dificultat):
# Configurar els paràmetres segons la dificultat
if dificultat == "Facil":
AMPLADA, ALCADA, NUM_MINES, escala, pos_ini = (
5, # Amplada del tauler
4, # Alçada del tauler
random.randint(4, 8), # Nombre de mines aleatori
2, # Escala per ampliar el tauler
(2, 2), # Posició inicial del punter
)
elif dificultat == "Dificil":
AMPLADA, ALCADA, NUM_MINES, escala, pos_ini = (
10,
8,
random.randint(15, 20),
1,
(4, 3),
)
contador_mines = NUM_MINES # Nombre de mines restants a marcar
# Crear el tauler lògic i visual
tauler = [[0 for _ in range(AMPLADA)] for _ in range(ALCADA)] # Estat del joc
visual = [[0 for _ in range(AMPLADA)] for _ in range(ALCADA)] # Estat visible del tauler
# Crear el TileGrid per mostrar el tauler
tauler_visual = displayio.TileGrid(imatges, pixel_shader=palette, width=AMPLADA, height=ALCADA, tile_width=16, tile_height=16)
# Crear el punter
punter = displayio.TileGrid(puntero, pixel_shader=palette2, width=1, height=1, tile_width=16, tile_height=16)
# Crear grups visuals
grup_tauler = displayio.Group(scale=escala)
grup_tauler.append(tauler_visual)
grup_punter = displayio.Group(scale=escala)
grup_punter.append(punter)
grup = displayio.Group()
grup.append(grup_tauler)
grup.append(grup_punter)
pant.show(grup)
# Funció per generar mines i calcular números
def generar_tauler(excloure_x, excloure_y):
# Evitar generar mines al voltant de la primera selecció
posicions = [
(x, y)
for x in range(AMPLADA)
for y in range(ALCADA)
if not (abs(x - excloure_x) <= 1 and abs(y - excloure_y) <= 1)
]
# Col·locar mines en posicions aleatòries
mines = []
while len(mines) < NUM_MINES:
seleccio = random.choice(posicions)
if seleccio not in mines:
mines.append(seleccio)
for x, y in mines:
tauler[y][x] = -1 # Indicar que hi ha una mina
# Comptar mines adjacents per a cada cel·la
for y in range(ALCADA):
for x in range(AMPLADA):
if tauler[y][x] != -1:
tauler[y][x] = comptar_mines_adjacents(x, y)
# Comptar el nombre de mines adjacents a una cel·la
def comptar_mines_adjacents(x, y):
mines = 0
for dy in range(-1, 2):
for dx in range(-1, 2):
nx, ny = x + dx, y + dy
if 0 <= nx < AMPLADA and 0 <= ny < ALCADA and tauler[ny][nx] == -1:
mines += 1
return mines
# Propagar cel·les buides visibles quan s'obri una cel·la sense mines adjacents
def propagar_buides(x, y):
pila = [(x, y)]
while pila:
cx, cy = pila.pop()
for dy in range(-1, 2):
for dx in range(-1, 2):
nx, ny = cx + dx, cy + dy
if 0 <= nx < AMPLADA and 0 <= ny < ALCADA and visual[ny][nx] == 0:
if tauler[ny][nx] == 0:
visual[ny][nx] = 1
tauler_visual[ny * AMPLADA + nx] = 1
pila.append((nx, ny))
elif tauler[ny][nx] > 0:
visual[ny][nx] = 1
tauler_visual[ny * AMPLADA + nx] = tauler[ny][nx] + 1
# Verificar si el jugador ha guanyat
def verificar_victoria():
for y in range(ALCADA):
for x in range(AMPLADA):
if tauler[y][x] != -1 and visual[y][x] == 0:
return False
return True
# Mostrar un missatge al centre de la pantalla
def mostrar_missatge(font, text, color):
missatge = label.Label(
font=font,
text=text,
color=color,
anchor_point=(0.5, 0.5),
anchored_position=(pant.width // 2, pant.height // 2),
)
grup.append(missatge)
pant.refresh()
return missatge
# Funció per pausar el joc
def pausa():
pregunta = label.Label(font, text=" Tornar a l'inici? ", color=0xFFA500, x=5, y=25)
tornar_inici = label.Label(font2, text=" ? SI ", color=0x0000FF, x=13, y=60)
continuar = label.Label(font2, text=" ? NO ", color=0x0000FF, x=13, y=90)
grup_pausa = displayio.Group()
grup_pausa.append(pregunta)
grup_pausa.append(tornar_inici)
grup_pausa.append(continuar)
pant.show(grup_pausa) # Mostrar pantalla de pausa
abans = 0
while True:
boto = ugame.buttons.get_pressed()
if not abans & ugame.K_RIGHT and boto & ugame.K_RIGHT:
reiniciar_joc()
break
if not abans & ugame.K_LEFT and boto & ugame.K_LEFT:
pant.show(grup)
break
abans = boto
# Reiniciar el joc tornant al menú inicial
def reiniciar_joc():
nonlocal continuar
continuar = False
# Variables inicials del joc
cx, cy = pos_ini # Posició inicial del punter
abans = 0 # Estat anterior dels botons
primer_moviment = True # Indica si és el primer moviment
continuar = True # Control del bucle principal
# Carregar efectes de so
so_explosio = open("explosio.wav", "rb")
so_victoria = open("victoria.wav", "rb")
sons = ugame.audio
sons.mute(False)
while continuar:
boto = ugame.buttons.get_pressed()
# Controlar el moviment del punter
if not abans & ugame.K_RIGHT and boto & ugame.K_RIGHT and cx < AMPLADA - 1:
cx += 1
if not abans & ugame.K_LEFT and boto & ugame.K_LEFT and cx > 0:
cx -= 1
if not abans & ugame.K_DOWN and boto & ugame.K_DOWN and cy < ALCADA - 1:
cy += 1
if not abans & ugame.K_UP and boto & ugame.K_UP and cy > 0:
cy -= 1
punter.x = cx * 16
punter.y = cy * 16
# Destapar cel·la amb el botó X
if not abans & ugame.K_X and boto & ugame.K_X:
if primer_moviment:
generar_tauler(cx, cy)
primer_moviment = False
if tauler_visual[cy * AMPLADA + cx] == 10:
contador_mines += 1
if tauler[cy][cx] == -1: # Si es trepitja una mina
tauler_visual[cy * AMPLADA + cx] = 11
for y in range(ALCADA):
for x in range(AMPLADA):
if tauler[y][x] == -1:
tauler_visual[y * AMPLADA + x] = 11 # Mostrar totes les mines
grup.remove(grup_punter)
missatge = mostrar_missatge(font, "Has perdut!", 0xFFFFFF)
sons.play(so_explosio)
cadena[0] = (255, 0, 0)
time.sleep(5)
cadena[0] = (0, 0, 0)
grup.remove(missatge)
reiniciar_joc()
elif tauler[cy][cx] == 0: # Si la cel·la és buida
propagar_buides(cx, cy)
else: # Si la cel·la conté un número
visual[cy][cx] = 1
tauler_visual[cy * AMPLADA + cx] = tauler[cy][cx] + 1
# Col·locar o treure una bandera amb el botó O
if not abans & ugame.K_O and boto & ugame.K_O:
if visual[cy][cx] == 0:
if tauler_visual[cy * AMPLADA + cx] == 10:
tauler_visual[cy * AMPLADA + cx] = 0
contador_mines += 1
else:
tauler_visual[cy * AMPLADA + cx] = 10
contador_mines -= 1
# Mostrar el nombre de mines restants amb el botó SELECT
if not abans & ugame.K_SELECT and boto & ugame.K_SELECT:
missatge = mostrar_missatge(font3, str(contador_mines), 0xFFFFFF)
time.sleep(2)
grup.remove(missatge)
# Pausar el joc amb el botó START
if not abans & ugame.K_START and boto & ugame.K_START:
pausa()
# Verificar si el jugador ha guanyat
if verificar_victoria():
grup.remove(grup_punter)
missatge = mostrar_missatge(font, "Has guanyat!", 0x00FF00)
sons.play(so_victoria)
cadena[0] = (0, 255, 0)
time.sleep(5)
cadena[0] = (0, 0, 0)
grup.remove(missatge)
reiniciar_joc()
abans = boto
while True:
dificultat = seleccionar_dificultat() # Seleccionar dificultat
iniciar_joc(dificultat) # Iniciar el joc

Esta obra de Oriol Boix está licenciada bajo una licencia no importada Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0.