// ноты для мелодии #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 // библиотека для работы с дисплеем #include // создаём объект класса QuadDisplay и передаём номера пинов CS, DI и ⎍ QuadDisplay qd(3, 2, 6); // номера цифровых пинов кнопок #define BUTTON_ONE 12 #define BUTTON_TWO 13 // номера цифровых пинов светодиодов #define LED_ONE A1 #define LED_TWO A0 // номер пина пищалки #define BUZZER A3 // таймер обратного отчёта #define TIME_START 30 // int timePlayerOne = TIME_START; int timePlayerTwo = TIME_START; // состояния игры enum State { OFF, PLAYER_ONE, PLAYER_TWO, }; // объявлеем переменную state State state; // массив мелодии при загрузке программы int startTune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4, NOTE_G4}; // массив длительности нот для мелодии при старте int durationStartTune[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500}; // запоминаем текущее время unsigned long startMillis = millis(); void setup() { // открываем монитор Serial-порта Serial.begin(9600); // инициализация дисплея qd.begin(); // кнопки в режим входа pinMode(BUTTON_ONE, INPUT); pinMode(BUTTON_TWO, INPUT); // светодиоды в режим выхода pinMode(LED_ONE, OUTPUT); pinMode(LED_TWO, OUTPUT); // сброс игры resetGame(); } void loop() { // если нажаты обе кнопки if (!digitalRead(BUTTON_ONE) && !digitalRead(BUTTON_TWO)) { // сбрасываем игру resetGame(); } // если нажата кнопка игрока «1» if (!digitalRead(BUTTON_ONE) && state == PLAYER_ONE) { // добовляем 20 секунд к времени игрока «1» timePlayerOne = timePlayerOne + 20; // пищим бузером tone(BUZZER, NOTE_A3, 100); // ход игрока «2» state = PLAYER_TWO; // гасим светодиод игрока «1» digitalWrite(LED_ONE, LOW); // зажигаем светодиод игрока «2» digitalWrite(LED_TWO, HIGH); } else if (!digitalRead(BUTTON_TWO) && state == PLAYER_TWO) { // если нажата кнопка игрока «2» // добовляем 20 секунд к времени игрока «2» timePlayerTwo = timePlayerTwo + 20; // пищим бузером tone(BUZZER, NOTE_B3, 100);\ // ход игрока «2» state = PLAYER_ONE; // гасим светодиод игрока «1» digitalWrite(LED_TWO, LOW); // зажигаем светодиод игрока «2» digitalWrite(LED_ONE, HIGH); } // если прошла 1 секунда if (millis() - startMillis > 1000) { // проверяем какой игрок ходит switch (state) { case PLAYER_ONE: // уменьшаем время игрока «1» на 1 секунду timePlayerOne--; break; case PLAYER_TWO: // уменьшаем время игрока «2» на 1 секунду timePlayerTwo--; break; } // выводим время обоих игроков в Serial-порт Serial.print(timePlayerOne); Serial.print("\t\t"); Serial.println(timePlayerTwo); // запоминаем текущее время startMillis = millis(); } // вывод оставшигося времени обоих игроков на дисплей // два первых сегмента время игрока «1», два следующих — игрока «2» qd.displayScore(timePlayerOne < 60 ? timePlayerOne : timePlayerOne / 60, timePlayerTwo < 60 ? timePlayerTwo : timePlayerTwo / 60); // если вышло время хотя бы у одного из игроков if (timePlayerOne == 0 || timePlayerTwo == 0) { // завершаем игру endGame(); } } // функция сброса игры void resetGame() { // гасим светодиоды обоих игроков digitalWrite(LED_ONE, LOW); digitalWrite(LED_TWO, LOW); // выводим на дисплей надпись «PLAY» qd.displayDigits(QD_P, QD_L, QD_A, QD_Y); // играем привествующую мелодию melodyStart(); // выставляем время обратного отчёта timePlayerOne = TIME_START; timePlayerTwo = TIME_START; // состояние игры в режим «OFF» state = OFF; // бесконечный цикл while (1) { // если нажата кнопка игрока «1» if (!digitalRead(BUTTON_ONE)) { // пищим бузером tone(BUZZER, NOTE_A3, 100); // ход игрока «1» state = PLAYER_ONE; // зажигаем светодиод игрока «1» digitalWrite(LED_ONE, HIGH); // гасим светодиод игрока «2» digitalWrite(LED_TWO, LOW); // выходим из бесконечного цикла break; } else if (!digitalRead(BUTTON_TWO)) { // если нажата кнопка игрока «2» // пищим бузером tone(BUZZER, NOTE_B3, 100); // ход игрока «2» state = PLAYER_TWO; // зажигаем светодиод игрока «2» digitalWrite(LED_TWO, HIGH); // гасим светодиод игрока «1» digitalWrite(LED_ONE, LOW); // выходим из бесконечного цикла break; } } // вывод оставшигося времени обоих игроков на дисплей // два первых сегмента время игрока «1», два следующих — игрока «2» qd.displayScore(timePlayerOne < 60 ? timePlayerOne : timePlayerOne / 60, timePlayerTwo < 60 ? timePlayerTwo : timePlayerTwo / 60); delay(1000); } // функция окончания игры void endGame() { // играем мелодию завершения игры melodyEnd(); // гасим все свтодиоды digitalWrite(LED_ONE, LOW); digitalWrite(LED_TWO, LOW); // пока не нажата ни одна кнопка любого игрока while (digitalRead(BUTTON_ONE) && digitalRead(BUTTON_TWO)) { // крутимся в бесконечном цикле } // сбрасываем игру resetGame(); } // функция проигрывания мелодии о начале игры void melodyStart() { for (int thisNote = 0; thisNote < 13; thisNote++) { // играем следующую ноту tone(BUZZER, startTune[thisNote], durationStartTune[thisNote]); delay(durationStartTune[thisNote]); // задержка между нотами delay(25); } } // функция проигрывания мелодии о завершении игры void melodyEnd() { for (int y = 0; y <= 3; y++) { // издаём звуковой сигнал tone(BUZZER, NOTE_G3, 300); delay(200); // издаём звуковой сигнал tone(BUZZER, NOTE_C3, 300); delay(200); } }