#define SequenceMaxLen 50 // Длина последовательности #define ShowingTime 300 // Длительность отображения элемента последовательности (мс) #define DelayBetweenLeds 200 // Задержка между отображением элементов (мс) #define WaitingTime 10000 // Время ожидания ввода (мс) #define RepeatRightSequence 1 // Нужно ли повторять правильную последовательность при проигрыше byte Sequence[SequenceMaxLen]; // Последовательность включения светодиодов byte CurrentLen; // Текущая длина последовательности int CurrentIndex; // Номер обрабатываемого элемента последовательности byte ButtonsNLeds[] = {2, 3, 4, 5}; // Номера выводов, к которым подключены кнопки и светодиоды byte ButtonCount = sizeof(ButtonsNLeds) / sizeof(ButtonsNLeds[0]); bool ButtonStillPressed; enum eMode {mStartNewGame, mShowingSequence, mRepeatSequence, mWaitingForButtons}; // Соответсвующие значения к переменным 0,1,2,3 eMode Mode; // Текущий режим: отображение последовательности/ожидание ввода unsigned long tm; // Переменная для отслеживания временных интервалов #define pin_Speaker 12 // Пин к которому подключен динамик int Notes[] = {880, 988, 1047, 1175}; // Частоты нот для каждой из кнопок (A5, B5, C6, D6) void SetPinMode(byte NewPinMode) { // Установка режимов работы пинов for (byte i = 0; i < ButtonCount; i++) //ButtonCount не надо изменять pinMode(ButtonsNLeds[i], NewPinMode); } void Blink(int Count, int DelayTime) { //Мерцание светодиодов SetPinMode(OUTPUT); //Режим работы всех пинов настроен как "ВЫХОД" for (byte t = 0; t < Count; t++) { for (byte i = 0; i < ButtonCount; i++) //ButtonCount не надо изменять digitalWrite(ButtonsNLeds[i], 1); // высокий сигнал на пинах,то есть светятся светодиоды delay(DelayTime); //пауза for (byte i = 0; i < ButtonCount; i++) //ButtonCount не надо изменять digitalWrite(ButtonsNLeds[i], 0); // низкий сигнал на пинах,то есть не светятся светодиоды delay(DelayTime); //пауза } } /*void Win() { // отвечает за динамики (не используем) tone(pin_Speaker, 2637, 125); delay(162); tone(pin_Speaker, 2093, 500); SetPinMode(OUTPUT); for (byte t = 0; t < 5; t++) { for (byte i = 0; i < ButtonCount; i++) { digitalWrite(ButtonsNLeds[i], 1); delay(50); digitalWrite(ButtonsNLeds[i], 0); delay(20); } } }*/ void setup() { Serial.begin(9600); randomSeed(analogRead(0));// считывает начальное рандомное число Mode = mStartNewGame; // m = 0; } void loop() { switch (Mode) { case mStartNewGame: { // Новая игра Serial.println("Mode = mStartNewGame"); for (byte i = 0; i < SequenceMaxLen; i++) // Создаем последовательность Sequence[i] = random(ButtonCount); SetPinMode(OUTPUT); // Установка режимов работы пинов Blink(3, 800); // Мерцание светодиодов delay(DelayBetweenLeds); // Пауза перед включением первого светодиода Mode = mShowingSequence; // Установили режим показывать последовательность Serial.println("Mode = mShowingSequence"); CurrentIndex = -1; // Номер обрабатываемого элемента последовательности CurrentLen = 1; // Текущая длина последовательности return; } case mRepeatSequence: //повторять ли последовательность if (RepeatRightSequence == 0) { Mode = mStartNewGame; return; } case mShowingSequence: { // Показываем последовательность if (CurrentIndex == -1) { CurrentIndex = 0; // Номер обрабатываемого элемента последовательности Serial.print("Sequence: "); Serial.print(Sequence[CurrentIndex]); digitalWrite(ButtonsNLeds[Sequence[0]], HIGH); // Загорает светодиод //tone(pin_Speaker, Notes[Sequence[0]], ShowingTime); отвечает за звук tm = millis() + ShowingTime; // Переменная для отслеживания временных интервалов return; } if (millis() >= tm) { digitalWrite(ButtonsNLeds[Sequence[CurrentIndex]], LOW); // Гасим светодиод CurrentIndex++; // Номер обрабатываемого элемента последовательности if (CurrentIndex < CurrentLen) { // Если показана еще не вся последовательность delay(DelayBetweenLeds); // Задержка между отображением элементов (мс) Serial.print(", "); Serial.print(Sequence[CurrentIndex]); digitalWrite(ButtonsNLeds[Sequence[CurrentIndex]], HIGH); // то включаем следующий светодиод // tone(pin_Speaker, Notes[Sequence[CurrentIndex]], ShowingTime); отвечает за звук tm = millis() + ShowingTime; } else { Serial.println(); if (Mode == mRepeatSequence) { Mode = mStartNewGame; // Начинаем новую игру delay(1000); } else { Mode = mWaitingForButtons; // Иначе переключаемся в режим ввода Serial.println("Mode = mWaitingForButtons"); SetPinMode(INPUT); CurrentIndex = 0; tm = millis() + WaitingTime; } } } return; } case mWaitingForButtons: { // Ожидаем ввода последовательности if (millis() > tm) { // Время вышло. Game over tone(pin_Speaker, 110, 800); Blink(10, 50); Mode = mRepeatSequence; // Показываем правильную последовательность CurrentIndex = -1; return; } for (byte i = 0; i < ButtonCount; i++) { if (digitalRead(ButtonsNLeds[i]) == HIGH) { // Если кнопка нажата delay(50); if (ButtonStillPressed) return; // Кнопка все еще нажата, прерываем обработку ButtonStillPressed = 1; Serial.print("Button pressed: "); Serial.print(i); tone(12, Notes[i], 300); if (i == Sequence[CurrentIndex]) { // Нажата верная кнопка Serial.println(" - Right!"); CurrentIndex++; if (CurrentIndex < CurrentLen) // Если введена еще не вся последовательность tm = millis() + WaitingTime; // то ожидаем следующую кнопку else { // Иначе (введена вся последовательность) delay(500); if (CurrentLen == SequenceMaxLen) { // Конец игры Win(); delay(500); Mode = mStartNewGame; // Начинаем новую игру return; } delay(800); CurrentLen++; // увеличиваем ее длину Mode = mShowingSequence; // и переключаем режим SetPinMode(OUTPUT); CurrentIndex = -1; Serial.println("Mode = mShowingSequence"); return; } } else { // Если нажата неверная кнопка Serial.println(" - Wrong!"); tone(pin_Speaker, 110, 800); SetPinMode(OUTPUT); for (int t = 0; t < 10; t++) { digitalWrite(ButtonsNLeds[i], HIGH); delay(50); digitalWrite(ButtonsNLeds[i], LOW); delay(50); } Mode = mRepeatSequence; // Показываем правильную последовательность CurrentIndex = -1; Serial.println("Mode = mRepeatSequence"); return; } return; } } ButtonStillPressed = 0; return; } } }