- Home
- iThink
- Programmazione per Ragazzi
- Quiz show in Python: un gioco a domande passo per passo
Quiz show in Python: un gioco a domande passo per passo
Divento Programmatore — Capitolo 2: Quiz Show: Diventa il re delle domande
Obiettivi di Apprendimento
Al termine di questo capitolo avrai costruito un Quiz Show multiplayer e imparerai a:
- Creare e gestire liste per memorizzare sequenze ordinate di elementi
- Usare i dizionari per associare coppie di informazioni (chiave-valore)
- Iterare sulle informazioni con il ciclo
for - Sfruttare la funzione
enumerate()per conoscere contemporaneamente la posizione e il valore degli elementi - Mescolare e ordinare dati con
random.shuffle() - Leggere e scrivere file di testo (
.txt) per salvare i punteggi e caricare le domande dall'esterno
Termini Fondamentali
| Termine | Simbolo | Significato | | --------- | --------- | ------------- | | Lista (list) | 🗃️ | Raccolta ordinata di elementi racchiusa tra parentesi quadre [] | | Indice (index) | 🏷️ | Numero intero (a partire da 0) che indica la posizione di un elemento nella lista | | Dizionario (dict) | 📖 | Raccolta non ordinata di coppie chiave-valore racchiusa tra parentesi graffe {} | | Chiave (key) | 🔑 | L'etichetta univoca che usi per cercare un valore in un dizionario | | Valore (value) | 📄 | Il dato effettivo associato alla chiave | | Ciclo for | 🔁 | Istruzione che ripete un blocco per ciascun elemento di una collezione | | enumerate() | 🔢 | Funzione che restituisce sia la posizione (indice) sia il valore degli elementi | | I/O su File | 💾 | Operazioni di Input/Output per leggere (read) e scrivere (write) dati su file | | with open() | 🔒 | Costrutto Python sicuro per aprire file garantendo chiusura automatica |
La Storia: La rivoluzione silenziosa dei quiz su schermo
Negli anni '70, quando i computer non avevano ancora schermi a colori né la capacità di mostrare video in alta definizione, c'era un tipo di software che andava a ruba nelle università e nelle prime scuole dotate di terminali: i giochi testuali a domande e risposte. Il computer stampava una domanda sulla carta o su uno schermo a fosfori verdi, e lo studente doveva digitare la risposta corretta.
Uno dei primissimi giochi di simulazione di successo fu The Oregon Trail, creata nel 1971 da tre insegnanti di storia. Per sopravvivere a un viaggio virtuale lungo la pista dell'Oregon, i giocatori dovevano rispondere a domande di logica, pianificazione e geografia. Se rispondevano correttamente, la carovana andava avanti; in caso contrario, incorrevano in imprevisti come il furto dei buoi o le malattie.
Oggi, quasi tutti i quiz moderni (dai quiz a premi televisivi alle app sul tuo smartphone come Trivia Crack o Kahoot!) si basano sulla stessa identica struttura dati: un elenco di domande, ciascuna con una serie di risposte possibili e un indicatore per quella corretta. Imparare a gestire queste strutture ti permetterà di creare non solo giochi a quiz, ma anche la logica dietro ai suggerimenti dei prodotti su Amazon o ai film su Netflix!
Concept 1: Le Liste (Un astuccio organizzato)
Immagina di avere un astuccio scolastico con scomparti numerati in fila. Nel primo scomparto metti una penna, nel secondo una matita, nel terzo una gomma. In programmazione, questo astuccio è una Lista. Una lista è una raccolta ordinata di elementi.
astuccio = ["penna", "matita", "gomma"]
Per estrarre un elemento dall'astuccio, devi usare il suo indice (la sua posizione). Attenzione! I computer iniziano sempre a contare da 0.
- Il primo elemento ha indice
0:astuccio[0]restituisce"penna" - Il secondo elemento ha indice
1:astuccio[1]restituisce"matita" - Il terzo elemento ha indice
2:astuccio[2]restituisce"gomma"
Se provi ad accedere a un indice che non esiste (ad esempio astuccio[5]), Python si arrabbierà e ti darà un errore chiamato IndexError.
Ecco altre funzioni utili per manipolare le liste:
# Aggiungere un elemento in fondo alla lista
astuccio.append("righello")
# Modificare un elemento esistente
astuccio[1] = "matita colorata" # Sostituisce "matita" con "matita colorata"
# Rimuovere un elemento tramite il suo valore
astuccio.remove("gomma")
# Sapere quanti elementi ci sono (lunghezza)
numero_oggetti = len(astuccio)
print("Ci sono", numero_oggetti, "oggetti nell'astuccio.")
Concept 2: I Dizionari (La tua rubrica segreta)
Se una lista è ottima per tenere le cose in ordine, non è molto comoda se vuoi associare informazioni tra loro (ad esempio: associare a ogni capitale il suo stato, o a ogni domanda la sua risposta corretta). Per questo tipo di dati usiamo il Dizionario.
Un dizionario è come una rubrica telefonica o un dizionario reale di parole: cerchi un nome (la Chiave) e trovi il numero di telefono o la definizione associata (il Valore).
capitale = {
"Italia": "Roma",
"Francia": "Parigi",
"Spagna": "Madrid"
}
Per trovare la capitale dell'Italia, ti basta interrogare il dizionario usando la chiave "Italia":
print(capitale["Italia"]) # Mostra a schermo: Roma
Regole dei dizionari:
- Le chiavi devono essere univoche (non puoi avere due chiavi
"Italia"nello stesso dizionario, altrimenti l'ultima sovrascriverà la prima) - I valori possono essere qualsiasi cosa: stringhe, numeri, liste o persino altri dizionari!
- Si creano usando le parentesi graffe
{}e le coppie sono separate da:(chiave: valore)
Concept 3: Il Ciclo for e la magia di enumerate()
Per scorrere gli elementi di una lista uno alla volta senza dover scrivere una riga di codice per ciascuno, usiamo il ciclo for:
ingredienti = ["farina", "uova", "zucchero"]
for ingrediente in ingredienti:
print("Prendi:", ingrediente)
E se volessimo mostrare un numero d'ordine per ogni ingrediente (es: "1. farina", "2. uova")? Dovremmo usare la funzione enumerate(). Questa funzione restituisce due cose a ogni giro del ciclo: l'indice (la posizione) e l'elemento.
for indice, ingrediente in enumerate(ingredienti, 1):
print(f"{indice}. {ingrediente}")
Nota: il parametro 1 dentro enumerate(ingredienti, 1) dice a Python di iniziare a numerare da 1 invece che da 0, per renderlo più leggibile e naturale per chi gioca!
Costruiamo il Gioco: Versione Base
Mettiamo insieme liste e dizionari per creare il nostro primo Quiz Show! Nel nostro codice base, il quiz avrà tre domande memorizzate in una lista di dizionari.
import random
# Lista di dizionari: ogni dizionario rappresenta una domanda
domande = [
{
"domanda": "Quale pianeta è noto come il Pianeta Rosso?",
"opzioni": ["Terra", "Marte", "Giove", "Saturno"],
"risposta": "Marte"
},
{
"domanda": "Quanti minuti ci sono in un'ora?",
"opzioni": ["50", "60", "80", "100"],
"risposta": "60"
},
{
"domanda": "Qual è l'animale terrestre più veloce del mondo?",
"opzioni": ["Leone", "Ghepardo", "Antilope", "Levriero"],
"risposta": "Ghepardo"
}
]
punteggio = 0
print("🎤 BENVENUTO AL QUIZ SHOW! 🎤\n")
for i, q in enumerate(domande, 1):
print(f"Domanda {i}: {q['domanda']}")
# Mostriamo le opzioni numerate
for idx, opt in enumerate(q["opzioni"], 1):
print(f" {idx}. {opt}")
scelta = int(input("\nLa tua risposta (numero): "))
risposta_data = q["opzioni"][scelta - 1]
if risposta_data == q["risposta"]:
print("✅ Esatto! +10 punti\n")
punteggio += 10
else:
print(f"❌ Sbagliato! La risposta corretta era: {q['risposta']}\n")
print(f"Fine del gioco! Punteggio finale: {punteggio} punti.")
Sfide: Fai salire di livello il tuo Quiz
Sfida 1 — Il Timer a tempo
Nei quiz televisivi reali, c'è sempre suspense prima di dare la risposta. Possiamo simulare un conto alla rovescia di suspense prima di sbloccare l'inserimento usando la libreria time e la sua funzione time.sleep(secondi), che mette in pausa il programma per una frazione di tempo.
import time
# ... prima di chiedere l'input
print("Preparati a rispondere... ", end="", flush=True)
for secondi in range(3, 0, -1):
print(f"{secondi}.. ", end="", flush=True)
time.sleep(0.3)
print("VAI!")
Sfida 2 — Salva il Record (High Score)
Vogliamo che il computer si ricordi del punteggio migliore anche dopo aver chiuso il programma. Per farlo dobbiamo usare i File. In Python, per aprire un file usiamo la funzione open() in combinazione con with, che assicura che il file venga chiuso correttamente dopo l'uso.
- Scrivere su file:
with open("record.txt", "w") as f: - Leggere da file:
with open("record.txt", "r") as f:
Sfida 3 — Domande da File Esterno
Invece di scrivere le domande dentro al codice Python, le caricheremo da un file di testo chiamato domande.txt. Ogni riga del file rappresenterà una domanda, con questo formato: Domanda|Opzione1,Opzione2,Opzione3,Opzione4|RispostaCorretta
Esempio: Qual è il colore del sole?|Giallo,Rosso,Blu,Verde|Giallo
Useremo il metodo .split("|") per dividere la riga in tre parti separate dal carattere |, e poi .split(",") per separare le 4 opzioni.
Sfida 4 — Modalità Multiplayer (A Turni)
Due giocatori si sfidano sullo stesso computer. Le domande vengono alternate tra Giocatore 1 e Giocatore 2, e alla fine il programma proclama il vincitore confrontando i punteggi!
Il Codice Completo con Tutte le Sfide
Copia questo codice completo in Thonny e salvalo come quiz_show.py. Crea anche un file domande.txt nella stessa cartella per inserire le tue domande personalizzate!
import random
import time
import os
# Sfida 3: Domande di default da usare se il file esterno domande.txt non esiste
DEFAULT_DOMANDE = [
{
"domanda": "Quale linguaggio di programmazione prende il nome da uno show comico inglese?",
"opzioni": ["Java", "Python", "C++", "Ruby"],
"risposta": "Python"
},
{
"domanda": "Cosa significa l'acronimo RAM?",
"opzioni": ["Random Access Memory", "Read Active Module", "Rapid Access Method", "Run Applications Mode"],
"risposta": "Random Access Memory"
},
{
"domanda": "Quale di queste NON è una parola chiave in Python?",
"opzioni": ["while", "if", "loop", "import"],
"risposta": "loop"
}
]
def carica_domande(filename="domande.txt"):
"""Sfida 3: Legge le domande da un file esterno. Se il file non esiste,
lo crea con le domande di default."""
if not os.path.exists(filename):
try:
with open(filename, "w", encoding="utf-8") as f:
for q in DEFAULT_DOMANDE:
opzioni_str = ",".join(q["opzioni"])
f.write(f"{q['domanda']}|{opzioni_str}|{q['risposta']}\n")
return DEFAULT_DOMANDE
except Exception:
return DEFAULT_DOMANDE
domande = []
try:
with open(filename, "r", encoding="utf-8") as f:
for riga in f:
riga = riga.strip()
if not riga or "|" not in riga:
continue
parti = riga.split("|")
if len(parti) == 3:
domande.append({
"domanda": parti[0],
"opzioni": parti[1].split(","),
"risposta": parti[2]
})
return domande if domande else DEFAULT_DOMANDE
except Exception:
return DEFAULT_DOMANDE
def leggi_record(filename="record_quiz.txt"):
"""Sfida 2: Legge il punteggio record corrente da file."""
if os.path.exists(filename):
try:
with open(filename, "r", encoding="utf-8") as f:
return int(f.read().strip())
except ValueError:
return 0
return 0
def salva_record(nuovo_record, filename="record_quiz.txt"):
"""Sfida 2: Salva il nuovo punteggio record su file."""
try:
with open(filename, "w", encoding="utf-8") as f:
f.write(str(nuovo_record))
except Exception as e:
print(f"Impossibile salvare il record: {e}")
def gioca_singolo(domande):
"""Esegue una partita a giocatore singolo con salvataggio record."""
punteggio = 0
random.shuffle(domande)
record = leggi_record()
print(f"\n🏆 Il record da battere è: {record} punti!")
for i, q in enumerate(domande):
print(f"\n--- DOMANDA {i+1} di {len(domande)} ---")
print(q["domanda"])
opzioni = list(q["opzioni"])
random.shuffle(opzioni)
for idx, opt in enumerate(opzioni, 1):
print(f" {idx}. {opt}")
# Sfida 1: Countdown di suspense
print("\nPreparati a rispondere... ", end="", flush=True)
for secondi in range(3, 0, -1):
print(f"{secondi}.. ", end="", flush=True)
time.sleep(0.3)
print("VAI!")
scelta_valida = False
while not scelta_valida:
try:
scelta = int(input("La tua risposta (1-4): "))
if 1 <= scelta <= 4:
scelta_valida = True
else:
print("Inserisci un numero compreso tra 1 e 4.")
except ValueError:
print("Devi inserire un numero intero!")
risposta_data = opzioni[scelta - 1]
if risposta_data == q["risposta"]:
print("✅ RISPOSTA CORRETTA! +10 punti.")
punteggio += 10
else:
print(f"❌ SBAGLIATO! La risposta esatta era: {q['risposta']}")
time.sleep(1)
print(f"\n🎉 Fine della partita! Punteggio totale: {punteggio} punti.")
if punteggio > record:
print(f"🔥 INCREDIBILE! Hai stabilito un NUOVO RECORD superando {record}!")
salva_record(punteggio)
else:
print(f"Punteggio record attuale: {record}")
def gioca_multiplayer(domande):
"""Sfida 4: Partita a turni alternati per due giocatori."""
punti_g1 = 0
punti_g2 = 0
random.shuffle(domande)
print("\n🎤 BENVENUTI ALLA SFIDA MULTIPLAYER! 🎤")
g1 = input("Nome Giocatore 1: ").strip() or "Giocatore 1"
g2 = input("Nome Giocatore 2: ").strip() or "Giocatore 2"
for i, q in enumerate(domande):
# Alterna il turno: pari al Giocatore 1, dispari al Giocatore 2
turno_g = g1 if i % 2 == 0 else g2
print(f"\n--- DOMANDA {i+1} per {turno_g.upper()} ---")
print(q["domanda"])
opzioni = list(q["opzioni"])
random.shuffle(opzioni)
for idx, opt in enumerate(opzioni, 1):
print(f" {idx}. {opt}")
scelta_valida = False
while not scelta_valida:
try:
scelta = int(input(f"{turno_g}, la tua scelta (1-4): "))
if 1 <= scelta <= 4:
scelta_valida = True
else:
print("Inserisci un numero compreso tra 1 e 4.")
except ValueError:
print("Inserisci un numero intero!")
risposta_data = opzioni[scelta - 1]
if risposta_data == q["risposta"]:
print("✅ ESATTO! +10 punti.")
if turno_g == g1:
punti_g1 += 10
else:
punti_g2 += 10
else:
print(f"❌ ERRORE! La risposta corretta era: {q['risposta']}")
time.sleep(1)
print("\n" + "=" * 40)
print("🏆 CLASSIFICA FINALE 🏆")
print(f" {g1}: {punti_g1} punti")
print(f" {g2}: {punti_g2} punti")
print("=" * 40)
if punti_g1 > punti_g2:
print(f"🎉 IL VINCITORE È {g1.upper()}! Ottimo lavoro!")
elif punti_g2 > punti_g1:
print(f"🎉 IL VINCITORE È {g2.upper()}! Ottimo lavoro!")
else:
print("🤝 UN PAREGGIO! Siete entrambi bravissimi.")
def main():
domande = carica_domande()
print("╔══════════════════════════════════════╗")
print("║ 🎤 QUIZ SHOW 🎤 ║")
print("╚══════════════════════════════════════╝")
print("1. Giocatore Singolo")
print("2. Sfida a 2 Giocatori (Multiplayer)")
scelta = input("\nSeleziona una modalità (1/2): ").strip()
if scelta == "2":
gioca_multiplayer(domande)
else:
gioca_singolo(domande)
if __name__ == "__main__":
main()
Analisi del Codice Completo
Analizziamo i punti più interessanti e complessi di questo codice:
1. Leggere e scrivere su file senza bloccare il programma
Nelle funzioni carica_domande, leggi_record e salva_record usiamo il costrutto with open(..., encoding="utf-8"). La codifica encoding="utf-8" è indispensabile per leggere e scrivere caratteri accentati (come à, è, ì, ò, ù) senza che il computer crashi o mostri caratteri strani (es: ò).
2. Suddivisione della riga (.split())
Nel caricamento delle domande, la riga del file è divisa in parti usando riga.split("|"). Se la riga è Quale animale...?|Leone,Ghepardo|Ghepardo, Python creerà una lista con tre elementi:
parti[0]="Quale animale...?"parti[1]="Leone,Ghepardo"parti[2]="Ghepardo"
Successivamente, facciamo un secondo split con la virgola parti[1].split(",") per ottenere la lista di opzioni ["Leone", "Ghepardo"].
3. Alternanza dei turni con l'operatore modulo (%)
Nella modalità multiplayer usiamo i % 2 == 0 per decidere a chi tocca. L'operatore % restituisce il resto della divisione. Se i (il numero della domanda corrente) è pari (0, 2, 4), il resto è 0 e tocca a Giocatore 1. Se i è dispari (1, 3, 5), il resto è 1 e tocca a Giocatore 2. È lo stesso metodo usato dai computer per alternare i pixel di colori diversi sullo schermo!
4. Gestione dei crash con try e except
Quando usiamo int(input(...)) per leggere la scelta del giocatore, se l'utente digita una lettera anziché un numero (ad esempio "due"), Python solleva un errore di tipo ValueError. Avvolgendo la richiesta in un blocco try e except ValueError, il programma intercetta l'errore, stampa un messaggio di avviso cortese e chiede nuovamente l'input senza bloccarsi.
Curiosità: Ada Lovelace
Lo sapevi che la prima persona al mondo definita "programmatrice" fu una donna di nome Ada Lovelace? Nel 1843, Ada descrisse un algoritmo per calcolare i numeri di Bernoulli usando un computer meccanico che non era stato ancora costruito!
Provaci tu! — Il Quiz di Classe
Modifica il file domande.txt inserendo 5 domande sui tuoi argomenti preferiti (es: videogiochi, serie TV o scienze). Sfida un tuo amico e scoprite chi ne sa di più.
Il Piccolo Glossario
| Termine | Definizione | | --------- | ------------- | | List / Lista | Una collezione ordinata di elementi racchiusi tra parentesi quadre. | | Index / Indice | La posizione di un elemento all'interno di una lista. Ricorda che in informatica inizia sempre da 0! | | Dictionary / Dizionario | Una collezione di coppie formate da una chiave (l'etichetta) e un valore (l'informazione). | | Key / Chiave | L'identificatore univoco usato per cercare un valore in un dizionario. | | Value / Valore | Il dato associato a una chiave all'interno del dizionario. | | for loop / Ciclo for | Struttura di controllo che consente di scorrere gli elementi di una collezione uno alla volta. | | enumerate() | Una funzione Python che restituisce sia la posizione (indice) sia il valore dell'elemento. | | random.shuffle() | Funzione della libreria random che mescola gli elementi di una lista direttamente "sul posto" (in-place). | | I/O su File | Operazioni di Input/Output per interagire con i file salvati sul disco fisso del computer. | | with open | Il modo raccomandato in Python per gestire i file garantendo la chiusura automatica delle risorse. | | ValueError | Errore sollevato quando una funzione riceve un argomento del tipo corretto ma con un valore non appropriato (es: convertire "ciao" in numero). |
Prossimo capitolo
Capitolo 3: Battaglia Navale Testuale
Matrici (liste di liste), coordinate cartesiane, cicli nidificati, corazzata 3 celle orientamento casuale, set per colpi sparati. 4 sfide: munizioni limitate, mappa dinamica, flotta 3 navi, corazzata multi-cella.
Questo post è un estratto dal libro "Divento Programmatore: Python e i Giochi" (Volume 2 della collana "Cervello Elettronico") di Rocco Balzamà. Target: 10-14 anni · ~180 pagine · Thonny + VS Code.
Per approfondire
- Variabili e tipi di dati in Python spiegati semplice
- Controllo di flusso in Python: if, for e while
- Indovina il numero: il primo gioco in Python
- Corsi e percorsi di programmazione