Introduzione
Ricordi il classico gioco Simon Says? È il progetto perfetto per imparare array, macchine a stati e gestione dell’input utente su Arduino. In questo tutorial, costruiremo un gioco Simon Says completamente funzionale usando quattro LED e quattro pulsanti, tutto simulato direttamente nel tuo browser con Velxio. Nessun hardware necessario!

Panoramica del Circuito
Diamo un’occhiata ai componenti e a come sono collegati.
Componenti
| Componente | ID | Scopo |
|---|---|---|
| Arduino Uno | arduino-uno | Il cervello del gioco |
| LED Rosso | led-red | Output per la sequenza rossa |
| LED Verde | led-green | Output per la sequenza verde |
| LED Blu | led-blue | Output per la sequenza blu |
| LED Giallo | led-yellow | Output per la sequenza gialla |
| Pulsante Rosso | button-red | Input utente per il rosso |
| Pulsante Verde | button-green | Input utente per il verde |
| Pulsante Blu | button-blue | Input utente per il blu |
| Pulsante Giallo | button-yellow | Input utente per il giallo |
Cablaggio
L’anodo (A) di ogni LED si collega a un pin digitale sull’Arduino, e il suo catodo (C) va a GND attraverso un resistore limitatore di corrente (simulato internamente). I pulsanti sono cablati con un piedino (1.l) a un pin digitale e l’altro piedino (2.l) a GND, utilizzando i resistori di pull-up interni dell’Arduino.
- LED Rosso: Pin 8 (filo rosso) all’anodo, catodo a GND (filo nero).
- LED Verde: Pin 9 (filo verde) all’anodo, catodo a GND.
- LED Blu: Pin 10 (filo blu) all’anodo, catodo a GND.
- LED Giallo: Pin 11 (filo giallo) all’anodo, catodo a GND.
- Pulsante Rosso: Pin 2 (filo azzurro) a 1.l, 2.l a GND.
- Pulsante Verde: Pin 3 (filo azzurro) a 1.l, 2.l a GND.
- Pulsante Blu: Pin 4 (filo azzurro) a 1.l, 2.l a GND.
- Pulsante Giallo: Pin 5 (filo azzurro) a 1.l, 2.l a GND.
Tutte le connessioni di massa condividono il pin GND dell’Arduino.
Panoramica del Codice
Apri l’editor di codice in Velxio per vedere lo sketch completo.

Costanti e Variabili
const int LED_PINS[] = {8, 9, 10, 11};
const int BUTTON_PINS[] = {2, 3, 4, 5};
const int NUM_LEDS = 4;
int sequence[100];
int sequenceLength = 0;
int currentStep = 0;
Definiamo array per i pin dei LED e dei pulsanti, in corrispondenza del cablaggio. sequence memorizza lo schema casuale (fino a 100 passi). sequenceLength tiene traccia di quanti passi il giocatore deve ripetere, e currentStep tiene traccia del progresso del giocatore.
Setup
void setup() {
Serial.begin(9600);
for (int i = 0; i < NUM_LEDS; i++) {
pinMode(LED_PINS[i], OUTPUT);
pinMode(BUTTON_PINS[i], INPUT_PULLUP);
}
randomSeed(millis());
newGame();
}
Impostiamo i pin dei LED come output e i pin dei pulsanti come input con pull-up interni (così i pulsanti leggono LOW quando premuti). randomSeed(millis()) garantisce una sequenza diversa ogni partita. newGame() avvia il primo round.
Logica di Gioco
newGame() resetta la lunghezza della sequenza a 1, aggiunge un passo casuale e riproduce la sequenza.
void newGame() {
sequenceLength = 1;
currentStep = 0;
addToSequence();
playSequence();
}
void addToSequence() {
sequence[sequenceLength - 1] = random(0, NUM_LEDS);
}
void playSequence() {
for (int i = 0; i < sequenceLength; i++) {
flashLED(sequence[i]);
delay(500);
}
}
void flashLED(int led) {
digitalWrite(LED_PINS[led], HIGH);
delay(300);
digitalWrite(LED_PINS[led], LOW);
}
playSequence() scorre la sequenza memorizzata, accendendo ogni LED per 300ms con un intervallo di 500ms.
Loop Principale
void loop() {
for (int i = 0; i < NUM_LEDS; i++) {
if (digitalRead(BUTTON_PINS[i]) == LOW) {
flashLED(i);
if (i == sequence[currentStep]) {
currentStep++;
if (currentStep == sequenceLength) {
delay(1000);
sequenceLength++;
currentStep = 0;
addToSequence();
playSequence();
}
} else {
// Pulsante sbagliato - game over
for (int j = 0; j < 3; j++) {
for (int k = 0; k < NUM_LEDS; k++) {
digitalWrite(LED_PINS[k], HIGH);
}
delay(200);
for (int k = 0; k < NUM_LEDS; k++) {
digitalWrite(LED_PINS[k], LOW);
}
delay(200);
}
newGame();
}
delay(300);
while (digitalRead(BUTTON_PINS[i]) == LOW);
}
}
}
Il loop controlla continuamente tutti i pulsanti. Quando un pulsante viene premuto (LOW), accende il LED corrispondente. Se il pulsante premuto corrisponde al passo previsto (sequence[currentStep]), avanziamo. Se il giocatore completa la sequenza, aggiungiamo un nuovo passo e riproduciamo la sequenza più lunga. Se è sbagliato, tutti i LED lampeggiano tre volte e inizia una nuova partita.
Concetti Chiave
- Array: Usare array per memorizzare i numeri dei pin e la sequenza di gioco rende il codice scalabile e pulito.
- Resistori di Pull-up Interni:
INPUT_PULLUPelimina i resistori esterni; i pulsanti leggono LOW quando premuti. - Debouncing: Il
delay(300)e il ciclowhile(digitalRead(...)==LOW)forniscono un semplice debouncing. - Casualità:
randomSeed(millis())erandom()generano sequenze imprevedibili. - Macchina a Stati: Il gioco tiene traccia di
currentStepesequenceLengthper gestire il progresso.
Insidie Comuni e Suggerimenti per il Debug
- I pulsanti non rispondono? Controlla che i pin dei pulsanti siano impostati su
INPUT_PULLUPe cablati correttamente (1.l al pin, 2.l a GND). - I LED non si accendono? Verifica che i pin dei LED siano
OUTPUTe che le connessioni anodo/catodo siano corrette. - Sequenza troppo veloce? Regola i valori di
delay()inflashLED()eplaySequence(). - Il gioco si resetta inaspettatamente? Assicurati che
randomSeed(millis())venga chiamato una sola volta insetup(). - Usa il Monitor Seriale: Aggiungi istruzioni
Serial.println()per eseguire il debug dei valori della sequenza.
Estensioni Suggerite
- Aggiungi un cicalino: Riproduci un tono per ogni colore del LED.
- Livelli di difficoltà: Aumenta la velocità man mano che la sequenza cresce.
- Punteggio massimo: Tieni traccia della sequenza più lunga raggiunta.
- Multigiocatore: Alterna i turni tra due giocatori.
- Feedback visivo: Usa diverse luminosità o schemi dei LED.
Provalo Tu Stesso!
Pronto a giocare? Apri l’esempio live su Velxio e avvia la simulazione. Premi i pulsanti per ripetere la sequenza. Quanto lontano riesci ad arrivare?
Buona costruzione!