Simon clone with Arduino Nano
A very simple tutorial with few basic components and an Nano or Uno: A clone of the world famous 1978 Simon by Milton Bradley
Components and supplies
1
Slide Switch
5
Pushbutton Switch, Momentary
1
Arduino Nano R3
6
Resistor 10k ohm
4
LED (generic)
1
Speaker, Piezo
4
Resistor 1k ohm
Project description
Code
simon.ino
arduino
1/************************************************************************************************* 2* 3* ARDUINO SIMON 1.0 4* 5* Feb/2022 Giovanni Verrua 6* 7* This program is free software: you can redistribute it and/or modify 8* it under the terms of the GNU General Public License as published by 9* the Free Software Foundation, either version 3 of the License, or 10* (at your option) any later version. 11* 12* This program is distributed in the hope that it will be useful, 13* but WITHOUT ANY WARRANTY; without even the implied warranty of 14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15* GNU General Public License for more details. 16* 17* You should have received a copy of the GNU General Public License 18* along with this program. If not, see <https://www.gnu.org/licenses/>. 19* ----------------------------------------------------------------------- 20* This is the classic 1978 Simon by Milton Bradley recreated with an 21* Arduino Uno or Nano (or possibly Mini Pro, etc.) 22* For game rules see: https://en.wikipedia.org/wiki/Simon_(game) 23* 24* ----------------------------------------------------------------------- 25* Hardware needed: 26* 1x Arduino Uno/Nano/etc. 27* 5x buttons (one per color plus one to start the game) 28* 4x leds (red, yellow, green, blue) 29* 1x switch (for easy/hard selection) - not needed if you opt for the power+level switch below 30* 7x pulldown resistors (any value between 10 kohm and 100 kohm) 31* 4x 1 kohm resistors (or one per led if you want to use more than a led per color) 32* 1x speaker (piezo or normal) 33* 34* (optional for power+level switch - see below) 35* 1 way, 3 positions switch 36* 1x 5v Zener diode 37* 1x 1N 4148 diode or any other equivalent diode 38* 1x 1 kohm resistor 39* ----------------------------------------------------------------------- 40* Connections (based on the #define below): 41* pin #2 -- 1 kohm resistor -- LED red -- GND 42* pin #3 -- 1 kohm resistor -- LED yellow -- GND 43* pin #4 -- 1 kohm resistor -- LED green -- GND 44* pin #5 -- 1 kohm resistor -- LED blue -- GND 45* 46* pin #6 -- 10..100 kohm pulldown resistor -- GND 47* pin #7 -- 10..100 kohm pulldown resistor -- GND 48* pin #8 -- 10..100 kohm pulldown resistor -- GND 49* pin #9 -- 10..100 kohm pulldown resistor -- GND 50* pin #12-- 10..100 kohm pulldown resistor -- GND 51* pin #13-- 10..100 kohm pulldown resistor -- GND 52* 53* pin #6 -- button for red --- +5V 54* pin #7 -- button for yellow --- +5V 55* pin #8 -- button for green --- +5V 56* pin #9 -- button for blue --- +5V 57* pin #12-- button for start --- +5V 58* pin #13-- level switch --- +5V 59* 60* pin #10 -- speaker -- GND 61* 62* NOTE: if you want to use a 3 positions switch for OFF / ON easy / ON hard you will need 63* to create the following schematic using a 1 way - 3 positions switch, 64* a 1N4148 diode, a 5V zener and a 1 kohm resistor. Be sure to make everything as explained 65* or you could fry your Arduino... 66* 67* --- 9-12v Power ---O ----O---- O----- off 68* (external) (switch) 69* O O------------------ easy level -------+-------- Arduino V.in 70* | 71* O O--+-[1N4148]- >|-- hard level -------+ 72* | 73* +--- 1 kohm resistor --+-------------------- Arduino pin# 13 74* | 75* +---|<-- 5v Zener --- Arduino GND 76* 77* 78**************************************************************************************************/ 79 80#define LED_RED 2 81#define LED_YEL 3 82#define LED_GRE 4 83#define LED_BLU 5 84 85#define BUT_RED 6 //Button for red light - put a 10-100 kohm pulldown resistor between this button and GND 86#define BUT_YEL 7 //Button for yellow light - put a 10-100 kohm pulldown resistor between this button and GND 87#define BUT_GRE 8 //Button for green light - put a 10-100 kohm pulldown resistor between this button and GND 88#define BUT_BLU 9 //Button for blue light - put a 10-100 kohm pulldown resistor between this button and GND 89 90#define TONEPIN 10 //Speaker pin 91 92#define BUT_RUN 12 //button Start - put a 10-100 kohm pulldown resistor between this button and GND 93#define GAMELEV 13 //switch that toogle level between hard (switch closed, HIGH) and easy (switch open, LOW) - put a 10-100 kohm pulldown resistor between this switch and GND 94 95#define TIMEOUT 5000 //Timeout 5 Seconds for the player to hit next light before to loose the game - Same to the original 1978 Simon 96#define LEVEASY 10 //10 lights sequence in the easy level \\__ NOTE: the original game had 4 difficulty levels (sequences of 8, 14, 20 and 31 light) 97#define LEVHARD 20 //20 lights sequence in the hard level / it also had 3 game modes; I implemented the most common only. 98#define GAMESPD 500 //milliseconds for every led/sound 99 100 101int statGame = 0; //0 = idle, 1 = game running 102 103//A = 220(red);C = 139(yellow); E = 82(octave lower)(green); E = 165(blue) -> original tones by 1978 Simon 104int tonSeq [4] { 220 , 139 , 82 , 165 }; 105 106int ledSeq [4] { LED_RED , LED_YEL , LED_GRE , LED_BLU}; 107int butSeq [4] { BUT_RED , BUT_YEL , BUT_GRE , BUT_BLU}; 108 109int gamSeq[LEVHARD]; //no need to initialize this array 110 111int pointer = 0; //game pointer (sequence) 112 113 114//===================================================================================== LIGHT_AND_SOUND 115void light_and_sound(int point) { 116 117 digitalWrite(ledSeq[point], HIGH); 118 tone(TONEPIN,tonSeq[point]); 119 delay(GAMESPD); 120 121 digitalWrite(ledSeq[point], LOW); 122 noTone(TONEPIN); 123 delay(GAMESPD/2); 124} 125 126//===================================================================================== SETUP 127void setup() { 128 129 randomSeed(analogRead(0)); 130 131 pinMode( BUT_RUN, INPUT); //initializing the digital pins 132 pinMode( GAMELEV, INPUT); //initializing the digital pins 133 134 for (int i=0; i<4;i++) { 135 pinMode( butSeq[i] ,INPUT); //initializing the digital pins 136 pinMode( ledSeq[i] ,OUTPUT); //initializing the digital pins 137 } 138 139} 140 141 142 143//===================================================================================== LOOP 144void loop() { 145 146 statGame = 0; 147 pointer = 0; 148 //-----------------------------------------------------------------------------------------------------idle 149 while (statGame == 0){ //idle 150 151 //--------------------------------------- idle sequence 152 digitalWrite(ledSeq[pointer], HIGH); 153 delay(200); 154 digitalWrite(ledSeq[pointer], LOW); 155 156 pointer++; //using pointer for the idle light sequence 157 if (pointer > 3) pointer = 0; 158 159 if (digitalRead(BUT_RUN) == HIGH) statGame = 1; //pressed the start button, entering the game... 160 161 } 162 163 //-----------------------------------------------------------------------------------------------------RESETTING GAME 164 unsigned long timeout = millis(); //tracking the game timeout 165 166 int playGame = 0; //0 = computer turn, 1 = player turn 167 int gameLevel = 0; //0 = easy (sequence of 10 lights), 1 = hard (sequence of 20 lights) 168 bool gameOver = false; //true if the player lost the game 169 170 pointer = 0; 171 172 if (digitalRead(GAMELEV) == HIGH) gameLevel = LEVHARD; //Level hard 173 else gameLevel = LEVEASY; //level easy 174 175 //-----------------------------------------------------------------------------------------------------IN GAME 176 177 while (statGame == 1){ // IN GAME 178 179 while (pointer < gameLevel && !gameOver) { 180 181 //--------------------------------------------------------------------------------\\- 182 if (playGame == 0) { //computer turn 183 184 delay(1000); 185 186 int rndValue = -1; 187 while ( rndValue < 0 || rndValue > 3) { 188 rndValue = random(4); //0 to 3 189 190 //a little explanation about the following line. The random() function often tends to repeat the same number over and over. 191 //the original Simon admits some replicated colors, but with Arduino it happens too often, IMO. 192 //So I decided to allow a replicated color every 3 step only [if it's the case]. Then: 193 //if the current color is == to the previous color and the current pointer isn't a multiple of three, 194 //I will call the random() function again. 195 //-------- 196 //if you don't care about repeated lights, can simply comment or delete the following line. 197 //changing the % 3 with %2 will give more repeated lights, changing with an higher value will 198 //reduce the chance of repeated lights. 199 if (pointer >0 && rndValue == gamSeq[pointer-1] && pointer % 3 != 0) rndValue = -1; 200 } 201 202 gamSeq[pointer] = rndValue; //assign the latest color to the array 203 204 for (int i=0; i <= pointer; i++) light_and_sound(gamSeq[i]); //playing the whole sequence 205 206 playGame = 1; 207 208 } 209 //--------------------------------------------------------------------------------/- 210 211 //--------------------------------------------------------------------------------\\- 212 if (playGame == 1) { //player turn 213 214 int j=0; 215 while (j <= pointer && !gameOver) { 216 217 if (timeout + TIMEOUT < millis()) {gameOver = true; j = pointer+1;} //game timeout 218 219 for (int i=0;i<4;i++) { 220 if (digitalRead(butSeq[i]) == HIGH) { //the player pressed a button, let me light the LED and see if it's the right one! 221 timeout = millis(); //resetting the timeout 222 light_and_sound(i); //lighting the led for the pressed button 223 if (i == gamSeq[j]) j++; //the player chosed the right color, step ahead until the end of the current sequence 224 else { i=4; gameOver = true;} //wrong color, sorry! 225 } 226 } 227 } 228 229 playGame = 0; 230 pointer++; 231 232 } 233 //--------------------------------------------------------------------------------/- 234 } 235 236 237 //---- game is over; let me see who's the winner! ;-) ----------------------------------\\- 238 statGame = 0; 239 delay(1000); 240 if (!gameOver) { //the player won the game: playing the victory jingle ;D 241 for (int j=0;j<20;j++) { 242 for (int i=0;i<4;i++) { 243 digitalWrite(ledSeq[i], HIGH); 244 tone(TONEPIN,tonSeq[i]*j); 245 delay(40); 246 digitalWrite(ledSeq[i], LOW); 247 noTone(TONEPIN); 248 //delay(10); 249 } 250 } 251 } 252 else { //boooh!!! Loser!!! 253 for (int i=0;i<4;i++) digitalWrite(ledSeq[i], HIGH); 254 tone(TONEPIN,80); 255 delay(2000); 256 for (int i=0;i<4;i++) digitalWrite(ledSeq[i], LOW); 257 noTone(TONEPIN); 258 delay(1000); 259 260 } 261 //--------------------------------------------------------------------------------------/- 262 } 263 264} 265
simon.ino
arduino
1/************************************************************************************************* 2* 3 4* ARDUINO SIMON 1.0 5* 6* Feb/2022 Giovanni Verrua 7* 8* This 9 program is free software: you can redistribute it and/or modify 10* it under 11 the terms of the GNU General Public License as published by 12* the Free Software 13 Foundation, either version 3 of the License, or 14* (at your option) any later 15 version. 16* 17* This program is distributed in the hope that it will be useful, 18* 19 but WITHOUT ANY WARRANTY; without even the implied warranty of 20* MERCHANTABILITY 21 or FITNESS FOR A PARTICULAR PURPOSE. See the 22* GNU General Public License 23 for more details. 24* 25* You should have received a copy of the GNU General 26 Public License 27* along with this program. If not, see <https://www.gnu.org/licenses/>. 28* 29 ----------------------------------------------------------------------- 30* 31 This is the classic 1978 Simon by Milton Bradley recreated with an 32* Arduino 33 Uno or Nano (or possibly Mini Pro, etc.) 34* For game rules see: https://en.wikipedia.org/wiki/Simon_(game) 35* 36 37* ----------------------------------------------------------------------- 38 39* Hardware needed: 40* 1x Arduino Uno/Nano/etc. 41* 5x buttons (one 42 per color plus one to start the game) 43* 4x leds (red, yellow, green, blue) 44* 45 1x switch (for easy/hard selection) - not needed if you opt for the power+level 46 switch below 47* 7x pulldown resistors (any value between 10 kohm and 100 kohm) 48* 49 4x 1 kohm resistors (or one per led if you want to use more than a led per color) 50 51* 1x speaker (piezo or normal) 52* 53* (optional for power+level switch 54 - see below) 55* 1 way, 3 positions switch 56* 1x 5v Zener diode 57* 1x 58 1N 4148 diode or any other equivalent diode 59* 1x 1 kohm resistor 60* ----------------------------------------------------------------------- 61 62* Connections (based on the #define below): 63* pin #2 -- 1 kohm resistor 64 -- LED red -- GND 65* pin #3 -- 1 kohm resistor -- LED yellow -- GND 66* 67 pin #4 -- 1 kohm resistor -- LED green -- GND 68* pin #5 -- 1 kohm resistor 69 -- LED blue -- GND 70* 71* pin #6 -- 10..100 kohm pulldown resistor -- 72 GND 73* pin #7 -- 10..100 kohm pulldown resistor -- GND 74* pin #8 -- 10..100 75 kohm pulldown resistor -- GND 76* pin #9 -- 10..100 kohm pulldown resistor -- 77 GND 78* pin #12-- 10..100 kohm pulldown resistor -- GND 79* pin #13-- 10..100 80 kohm pulldown resistor -- GND 81* 82* pin #6 -- button for red --- +5V 83* 84 pin #7 -- button for yellow --- +5V 85* pin #8 -- button for green --- +5V 86* 87 pin #9 -- button for blue --- +5V 88* pin #12-- button for start --- +5V 89* 90 pin #13-- level switch --- +5V 91* 92* pin #10 -- speaker -- GND 93* 94 95* NOTE: if you want to use a 3 positions switch for OFF / ON easy / ON 96 hard you will need 97* to create the following schematic using a 1 way - 3 positions 98 switch, 99* a 1N4148 diode, a 5V zener and a 1 kohm resistor. Be sure to make 100 everything as explained 101* or you could fry your Arduino... 102* 103* 104 --- 9-12v Power ---O ----O---- O----- off 105* (external) (switch) 106* 107 O O------------------ easy level -------+-------- 108 Arduino V.in 109* | 110 111* O O--+-[1N4148]- >|-- hard level -------+ 112* 113 | 114* +--- 115 1 kohm resistor --+-------------------- Arduino pin# 13 116* | 117 118* +---|<-- 5v 119 Zener --- Arduino GND 120* 121* 122 123**************************************************************************************************/ 124 125#define 126 LED_RED 2 127#define LED_YEL 3 128#define LED_GRE 4 129#define LED_BLU 5 130 131#define 132 BUT_RED 6 //Button for red light - put a 10-100 kohm pulldown resistor between 133 this button and GND 134#define BUT_YEL 7 //Button for yellow light - put a 10-100 135 kohm pulldown resistor between this button and GND 136#define BUT_GRE 8 //Button 137 for green light - put a 10-100 kohm pulldown resistor between this button and GND 138#define 139 BUT_BLU 9 //Button for blue light - put a 10-100 kohm pulldown resistor between 140 this button and GND 141 142#define TONEPIN 10 //Speaker pin 143 144#define BUT_RUN 145 12 //button Start - put a 10-100 kohm pulldown resistor between this button and 146 GND 147#define GAMELEV 13 //switch that toogle level between hard (switch closed, 148 HIGH) and easy (switch open, LOW) - put a 10-100 kohm pulldown resistor between 149 this switch and GND 150 151#define TIMEOUT 5000 //Timeout 5 Seconds for the player 152 to hit next light before to loose the game - Same to the original 1978 Simon 153#define 154 LEVEASY 10 //10 lights sequence in the easy level \\__ NOTE: the original game 155 had 4 difficulty levels (sequences of 8, 14, 20 and 31 light) 156#define LEVHARD 157 20 //20 lights sequence in the hard level / it also had 3 game modes; 158 I implemented the most common only. 159#define GAMESPD 500 //milliseconds for every 160 led/sound 161 162 163int statGame = 0; //0 = idle, 1 = game running 164 165//A 166 = 220(red);C = 139(yellow); E = 82(octave lower)(green); E = 165(blue) -> original 167 tones by 1978 Simon 168int tonSeq [4] { 220 , 139 , 82 , 165 }; 169 170 171int ledSeq [4] { LED_RED , LED_YEL , LED_GRE , LED_BLU}; 172int butSeq 173 [4] { BUT_RED , BUT_YEL , BUT_GRE , BUT_BLU}; 174 175int gamSeq[LEVHARD]; //no 176 need to initialize this array 177 178int pointer = 0; //game pointer (sequence) 179 180 181 182//===================================================================================== 183 LIGHT_AND_SOUND 184void light_and_sound(int point) { 185 186 digitalWrite(ledSeq[point], 187 HIGH); 188 tone(TONEPIN,tonSeq[point]); 189 delay(GAMESPD); 190 191 192 digitalWrite(ledSeq[point], LOW); 193 noTone(TONEPIN); 194 195 delay(GAMESPD/2); 196} 197 198//===================================================================================== 199 SETUP 200void setup() { 201 202 randomSeed(analogRead(0)); 203 204 pinMode( 205 BUT_RUN, INPUT); //initializing the digital pins 206 pinMode( GAMELEV, INPUT); 207 //initializing the digital pins 208 209 for (int i=0; i<4;i++) { 210 pinMode( 211 butSeq[i] ,INPUT); //initializing the digital pins 212 pinMode( ledSeq[i] 213 ,OUTPUT); //initializing the digital pins 214 } 215 216} 217 218 219 220//===================================================================================== 221 LOOP 222void loop() { 223 224 statGame = 0; 225 pointer = 0; 226 227 //-----------------------------------------------------------------------------------------------------idle 228 229 while (statGame == 0){ //idle 230 231 //--------------------------------------- 232 idle sequence 233 digitalWrite(ledSeq[pointer], HIGH); 234 delay(200); 235 236 digitalWrite(ledSeq[pointer], LOW); 237 238 pointer++; 239 //using pointer for the idle light sequence 240 if (pointer > 3) pointer 241 = 0; 242 243 if (digitalRead(BUT_RUN) == HIGH) statGame = 1; //pressed 244 the start button, entering the game... 245 246 } 247 248 249 //-----------------------------------------------------------------------------------------------------RESETTING 250 GAME 251 unsigned long timeout = millis(); //tracking the game timeout 252 253 254 int playGame = 0; //0 = computer turn, 1 = player turn 255 int 256 gameLevel = 0; //0 = easy (sequence of 10 lights), 1 = hard (sequence of 20 lights) 257 258 bool gameOver = false; //true if the player lost the game 259 260 pointer 261 = 0; 262 263 if (digitalRead(GAMELEV) == HIGH) gameLevel = LEVHARD; //Level 264 hard 265 else gameLevel = LEVEASY; //level easy 266 267 268 //-----------------------------------------------------------------------------------------------------IN 269 GAME 270 271 while (statGame == 1){ // IN GAME 272 273 while 274 (pointer < gameLevel && !gameOver) { 275 276 //--------------------------------------------------------------------------------\\- 277 278 if (playGame == 0) { //computer turn 279 280 delay(1000); 281 282 283 int rndValue = -1; 284 while 285 ( rndValue < 0 || rndValue > 3) { 286 rndValue = 287 random(4); //0 to 3 288 289 //a little explanation 290 about the following line. The random() function often tends to repeat the same number 291 over and over. 292 //the original Simon admits some replicated 293 colors, but with Arduino it happens too often, IMO. 294 //So 295 I decided to allow a replicated color every 3 step only [if it's the case]. Then: 296 297 //if the current color is == to the previous color and 298 the current pointer isn't a multiple of three, 299 //I 300 will call the random() function again. 301 //-------- 302 303 //if you don't care about repeated lights, can simply 304 comment or delete the following line. 305 //changing 306 the % 3 with %2 will give more repeated lights, changing with an higher value will 307 308 //reduce the chance of repeated lights. 309 if 310 (pointer >0 && rndValue == gamSeq[pointer-1] && pointer % 3 != 0) rndValue = -1; 311 312 } 313 314 gamSeq[pointer] 315 = rndValue; //assign the latest color to the array 316 317 for 318 (int i=0; i <= pointer; i++) light_and_sound(gamSeq[i]); //playing the whole sequence 319 320 321 playGame = 1; 322 323 324 } 325 //--------------------------------------------------------------------------------/- 326 327 328 //--------------------------------------------------------------------------------\\- 329 330 if (playGame == 1) { //player turn 331 332 int 333 j=0; 334 while (j <= pointer && !gameOver) { 335 336 337 if (timeout + TIMEOUT < millis()) {gameOver = true; j = pointer+1;} 338 //game timeout 339 340 for (int i=0;i<4;i++) { 341 if 342 (digitalRead(butSeq[i]) == HIGH) { //the player pressed a button, let me light 343 the LED and see if it's the right one! 344 timeout 345 = millis(); //resetting the timeout 346 light_and_sound(i); 347 //lighting the led for the pressed button 348 if 349 (i == gamSeq[j]) j++; //the player chosed the right color, step ahead until the 350 end of the current sequence 351 else { 352 i=4; gameOver = true;} //wrong color, sorry! 353 } 354 355 } 356 } 357 358 359 playGame = 0; 360 pointer++; 361 362 363 } 364 //--------------------------------------------------------------------------------/- 365 366 } 367 368 369 //---- game is over; let 370 me see who's the winner! ;-) ----------------------------------\\- 371 statGame 372 = 0; 373 delay(1000); 374 if (!gameOver) { //the player 375 won the game: playing the victory jingle ;D 376 for (int j=0;j<20;j++) 377 { 378 for (int i=0;i<4;i++) { 379 digitalWrite(ledSeq[i], 380 HIGH); 381 tone(TONEPIN,tonSeq[i]*j); 382 383 delay(40); 384 digitalWrite(ledSeq[i], 385 LOW); 386 noTone(TONEPIN); 387 //delay(10); 388 389 } 390 } 391 } 392 else 393 { //boooh!!! Loser!!! 394 for (int i=0;i<4;i++) digitalWrite(ledSeq[i], 395 HIGH); 396 tone(TONEPIN,80); 397 delay(2000); 398 399 for (int i=0;i<4;i++) digitalWrite(ledSeq[i], 400 LOW); 401 noTone(TONEPIN); 402 delay(1000); 403 404 405 } 406 //--------------------------------------------------------------------------------------/- 407 408 } 409 410} 411
Downloadable files
Schematics (made using TinkerCad)
You can use Arduino Uno, Nano or any compatible (should work with most Arduinos)
Schematics (made using TinkerCad)

Comments
Only logged in users can leave comments