Think Go: Briscola è il mio primo videogioco: un progetto personale realizzato in Go, con interfaccia grafica Fyne, nato per mettere in pratica le mie conoscenze informatiche e approfondire un linguaggio che mi sta appassionando.
Qui ne racconto il percorso, dalla progettazione alla distribuzione. L'obiettivo non era soltanto scrivere un gioco funzionante, ma affrontare architettura, esperienza utente, test e automazione delle build all'interno dello stesso progetto.
Perché proprio la briscola
La briscola è un gioco che conosco e che preferisco alla scopa. Mi sembrava una scelta naturale per realizzare qualcosa di vicino alla tradizione italiana, mantenendo un carattere leggero e divertente.
L'ispirazione arriva anche dai giochi che vedevo nei primi computer Windows, come Spider: applicazioni immediate, capaci di intrattenere senza richiedere una lunga preparazione. Volevo riprendere quello spirito con un progetto dal codice consultabile e con un'identità personale.
Dietro la semplicità di una partita, però, si nascondono problemi interessanti per uno sviluppatore. Bisogna rappresentare il mazzo, distribuire le carte, gestire i turni, calcolare i punti e definire come risponde il computer. È un banco di prova in cui le scelte di progettazione diventano subito visibili.
Imparare Go attraverso un progetto completo
Mi sono avvicinato a Go apprezzandone la compilazione, le prestazioni e le possibilità di distribuzione su sistemi diversi. Dopo l'esperienza con OpenDSA Reading, mi interessava esplorare un percorso che mi permettesse di partire dal mio ambiente Linux e preparare il software anche per Windows e macOS.
Il gioco nasce quindi da due obiettivi collegati: imparare meglio il linguaggio e applicare il metodo acquisito durante gli studi e il lavoro. Non volevo fermarmi a un esercizio isolato, ma arrivare a qualcosa che altre persone potessero scaricare, usare e commentare.
È anche un'occasione per studiare organizzazione del codice, gestione degli errori e distribuzione. Chi sta imparando può seguire questi aspetti oltre alla sola logica delle carte.
Un'architettura divisa per responsabilità
Il gioco è separato in cinque file principali:
| File | Compito |
|---|---|
card.go |
Definizione delle carte e logica di base |
deck.go |
Gestione del mazzo |
player.go |
Giocatore umano e avversario controllato dal computer |
game.go |
Regole e funzionamento della partita |
main.go |
Interfaccia grafica e coordinamento |
A questi si aggiungono gli elementi di gestione del progetto, come go.mod per le dipendenze.
Il principio è mantenere responsabilità riconoscibili. Se voglio intervenire sul mazzo, devo sapere dove cercare; se voglio modificare la presentazione delle informazioni, non dovrei confonderla con le regole della partita.
Questa organizzazione poggia su interfacce focalizzate, separazione dei compiti e possibilità di estendere il progetto. La manutenibilità diventa così una scelta da fare mentre si scrive, non un intervento da rimandare alla fine.
L'avversario: tre approcci diversi
Il gioco prevede tre livelli di intelligenza artificiale, da un comportamento più semplice fino a strategie più articolate: scelte casuali, valutazioni euristiche e minimax con potatura alfa-beta.
L'idea è offrire un avversario che provi a vincere senza trasformare ogni partita in un'esperienza punitiva. È previsto anche un adattamento al livello di gioco, e riconosco che il passaggio tra i comportamenti non è sempre preciso.
È un aspetto che mi interessa proprio perché unisce teoria e risultato visibile: una strategia può essere elegante sulla carta, ma poi deve produrre una partita comprensibile e piacevole per chi gioca.
Fyne e l'interfaccia del gioco
Per la parte grafica ho scelto Fyne. L'interfaccia è essenziale, con carte selezionabili, informazioni sulla partita e comandi pensati per ridurre i passaggi necessari.
Le carte vengono disegnate attraverso gli elementi grafici dell'applicazione. Il tema chiaro o scuro contribuisce a integrare il gioco nell'ambiente che la persona usa abitualmente.
La scelta centrale è rendere leggibili le conseguenze delle azioni: quale carta è stata giocata, a chi spetta il turno e come cambia il punteggio. A questo servono evidenziazioni, animazioni e riscontri immediati che accompagnano la partita.
Semplicità visibile, organizzazione dietro le quinte
Un clic su una carta deve corrispondere a un'azione chiara. Dietro quel gesto, il programma aggiorna lo stato della partita e coordina ciò che viene mostrato.
Gestione degli errori, validazione degli input e logging sono gli strumenti con cui seguo il comportamento del software. Le goroutine si occupano del coordinamento delle attività e della gestione delle operazioni asincrone.
L'interfaccia minimale non implica quindi assenza di struttura. Significa mostrare soltanto ciò che serve nel momento giusto, lasciando le funzioni ulteriori nei menu invece di occupare continuamente il tavolo da gioco.
Test e metriche del progetto
Qualche numero per dare un'idea delle dimensioni: oltre 1.200 righe di codice, 89 test e una copertura dichiarata del 98%. La complessità ciclomatica media è di 3,2, i tempi di risposta sono nell'ordine dei 2 millisecondi, il binario resta sotto i 5 MB e l'utilizzo di memoria sotto i 16 MB.
Sono i valori rilevati sul progetto al momento in cui l'ho presentato, non misurazioni ripetute in seguito.
Il messaggio che voglio trasmettere attraverso questi indicatori è l'attenzione al processo: non soltanto completare una funzione, ma chiedersi come venga verificata e quanto sia semplice mantenerla. Test dei componenti, integrazione, benchmark e rapporti di copertura rendono visibile questa parte del lavoro.
Accessibilità come parte della progettazione
Tra gli obiettivi del progetto ci sono contrasto leggibile, navigazione da tastiera e compatibilità con strumenti di accessibilità, compresi gli screen reader.
Mi interessa che la semplicità non riguardi soltanto il numero di pulsanti. Anche capire il turno, leggere il punteggio e riconoscere le carte disponibili fa parte dell'esperienza.
Sono aspetti che rientrano nella qualità del prodotto insieme alla logica di gioco: un programma deve permettere alle persone di usare ciò che è stato costruito, non limitarsi ad averlo implementato.
Build automatiche e distribuzione
Un passaggio importante del progetto è l'uso di GitHub Actions per automatizzare la preparazione delle build. Ho organizzato una pipeline che produce gli eseguibili destinati a Windows, macOS e Linux.
La distribuzione passa dalla cartella delle build del progetto, raggiungibile attraverso il mio profilo GitHub e il sito personale. Chi preferisce studiare il programma può partire dal sorgente e dalla documentazione.
Esistono anche un Makefile e possibilità di packaging ulteriori. Docker e integrazioni con altri canali di distribuzione restano possibilità aperte, distinte da ciò che ho effettivamente utilizzato.
Ho avviato inoltre i contatti con il gruppo di Ufficio Zero per una possibile presenza nei loro repository: è una prospettiva, distinta dalla pubblicazione del progetto sul mio GitHub.
Un piccolo gioco per ragionare sullo sviluppo software
La briscola mi ha permesso di collegare apprendimento del linguaggio, progettazione e automazione. È questo il valore che vorrei condividere con chi mi segue e con chi sta iniziando a programmare.
Il mio approccio si riassume in tre idee: progettare pensando alla qualità, automatizzare i passaggi ripetitivi e migliorare il progetto nel tempo. Un gioco di carte offre un contesto concreto in cui provare ad applicarle.
Se lo provate, mi interessa sapere che cosa funziona bene e che cosa si potrebbe migliorare. Segnalazioni di problemi, suggerimenti e contributi possono aiutarmi a far crescere il progetto e a farne il punto di partenza per nuovi approfondimenti sulla programmazione.