Проект 15. Игра "Simon" говорит

Игра на развитии памяти "Simon" теперь реализована на Arduino с помощью Trema Set Shield и новых Trema-модулей кнопок со светодиодами.

Правила игры:

Вы должны повторить последовательность цветов, нажимая кнопки в той же последовательности, в которой загорались светодиоды. На 1 уровне зажжется на пол секунды один из трех светодиодов кнопки. После того как он потухнет, нужно нажать кнопку с соответствующим светодиодом. На 2 уровне, зажжется тот же светодиод, а потом еще один из трех, нужно нажать кнопку с соответствующим первым светодиодом, а потом кнопу с други загоревшимся светодиодом. На уровне три последовательно зажгутся три светодиода и т. д. Если вы нажмёте не на ту кнопку, ошибетесь в последовательности, то на 1 секунду зажгутся все светодиоды и игра начнется с 1 уровня.

Нам понадобится:

Для реализации проекта нам необходимо установить следующие библиотеки:

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Схема подключения:

Перед подключением модулей, закрепите винтами нейлоновые стойки в отверстиях секций 3 и 4 Trema Set Shield.

Код программы:

#include <iarduino_OLED.h>                                  // Подключаем библиотеку iarduino_OLED.
iarduino_OLED myOLED(0x3C);                                 // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C.
extern uint8_t MediumFont[];                                // Подключаем шрифт MediumFont.
                                                            //
const uint8_t pinLed[3] = {1,A2, 5};                        // Создаем массив констант с № входов к которым подключены светодиоды.
const uint8_t pinKey[3] = {A0,2,A3};                        // Создаем массив констант с № входов к которым подключены кнопки.
                                                            //
uint8_t task[99];                                           // Создаем массив заданий (последовательность цветов).
uint8_t level   = 0;                                        // Создаем переменную для хранения № текущего уровня.
uint8_t numKey  = 0;                                        // Создаем переменную для хранения № нажатой клавиши.
uint8_t sumKey  = 0;                                        // Создаем переменную для подсчета количества нажатий клавиш.
bool    start   = 1;                                        // Создаем флаг старта.
                                                            //
void setup()                                                //
{                                                           //
  for(int i=0; i<3; i++)                                    // В цикле конфигурируем выводы и включаем светодиоды.
  {                                                         //
    pinMode(pinLed[i],OUTPUT);                              // Переводим выводы pinLed в режим выхода.
    digitalWrite(pinLed[i],LOW);                            // Выключаем светодиоды.
    pinMode(pinKey[i],INPUT);                               // Переводим выводы pinKey в режим выхода.
    randomSeed(analogRead(A1));                             // Назначаем случайное число со входа A0, для генератора random().
  }                                                         //
  myOLED.begin();                                           // Инициируем работу с дисплеем.
  myOLED.setFont(MediumFont);                               // Указываем шрифт который требуется использовать для вывода цифр и текста.
}                                                           //
void loop()                                                 //
{                                                           //
  numKey = 3;                                               // Присваиваем переменой № нажатой клавиши число 3.
  for(int i=0; i<3; i++)                                    // В цикле фиксируем нажатие одной из трех клавиш.
  {                                                         //
    if(digitalRead(pinKey[i]))                              // Если нажата клавиша.
    {                                                       //
      numKey = i; sumKey++;                                 // Сохраняем номер нажатой клавиши, увеличиваем количество нажатий клавиши.
    }                                                       //
  }                                                         //
  if(numKey<3)                                              // Если номер нажатой клавиши меньше 3.
  {                                                         //
    digitalWrite(pinLed[numKey],1);                         // Включаем светодиод нажатой клавиши.
    while(digitalRead(pinKey[numKey])){delay(50);}          // Ждем пока не отпустят кнопку.
    digitalWrite(pinLed[numKey],0);                         // Выключаем светодиод нажатой клавиши.
    if(task[sumKey-1] != numKey){level = 0; start = 1;}     // Если ошибка, то переходим на 0 уровень.
    if(!start && sumKey>level){level++; start = 1;}         // Если нет ошибок, то увеличиваем уровень.
  }                                                         //
  myOLED.print(level, OLED_C, OLED_C);                      // Выводим уровень на экран.
  if(start)                                                 // Если начат новый уровень.
  {                                                         //
    start = sumKey = 0;                                     // Запрещаем начинать новый уровень и обнуляем переменную подсчета количества нажатий клавиш.
    task[level] = random(0,3);                              // Придумываем последний цвет от 0 до 2.
    if(level == 0)                                          // Если начат нулевой уровень.
    {                                                       //
      for(int i=0; i<3; i++){digitalWrite(pinLed[i],1);}    // Включаем все светодиоды.
      delay(1000);                                          // Задержка 1 с.
      for(int i=0; i<3; i++){digitalWrite(pinLed[i],0);}    // Выключаем все светодиоды.
    }                                                       //
    delay(500);                                             // Задержка 500 мс.
    for(int i=0; i<=level; i++)                             // В цикле выводим всю последовательность цветов.
    {                                                       //
      delay(500); digitalWrite(pinLed[task[i]],1);          // Включаем очередной светодиод.
      delay(500); digitalWrite(pinLed[task[i]],0);          // Выключаем очередной светодиод.
    }                                                       //
  }                                                         //
}                                                           //

Алгоритм работы:

В начале скетча (до кода setup) выполняются следующие действия:

В коде setup выполняются следующие действия:

  • Переводим все выводы pinKey в режим входа для кнопок, а все выводы pinLed в режим выхода для светодиодов кнопок.
  • Гасим все светодиоды.
  • Назначаем случайное число со входа A0, для генератора random().
  • Инициируем OLED дисплей и указываем шрифт для работы.

В коде loop выполняются следующие действия:

  • Присваиваем переменой № нажатой клавиши число 3.
  • В цикле фиксируем нажатие одной из трех клавиш. Если нажата клавиша, то сохраняем номер нажатой клавиши, увеличиваем количество нажатий клавиши.
  • Если номер нажатой клавиши меньше 3. Включаем светодиод нажатой клавиши. Ждем пока не отпустят кнопку. Выключаем светодиод нажатой клавиши.
  • Если ошибка, то переходим на 0 уровень.
  • Если нет ошибок, то увеличиваем уровень.
  • Выводим уровень на экран.
  • Если начат новый уровень.
  • Придумываем последний цвет от 0 до 2.
  • Если начат нулевой уровень. Включаем все светодиоды. Ждем одну секунду. Выключаем все светодиоды.
  • В цикле выводим всю последовательность цветов, включаем и выключая очередной светодиод.

Ссылки:

Обсуждение