Пишем для Arduino на C++ простенькую игру и изучаем тернарный оператор ?. 

Тернарный оператор (от латинского слова ternarius — тройной) — это, в языке Си, оператор, состоящий из двух символов ? и :. Тернарный оператор формирует условную операцию, возвращающую свой второй или третий операнд в зависимости от результата вычисления заданного логического выражения.

Легенда игры: 

В Голливудских боевиках, часто, главный герой, спасая человечество, становятся перед выбором: какой провод резать, красный или синий? Вероятность правильного выбора в этой ситуации 50%. А если потренироваться, мы сможем повысить свои шансы на успех?

Задание на проектирование игры-тренажёра «Красный или синий».

В игре должна быть интерактивность. На принятие решения игроку даётся 60 секунд. За это время игрок должен принять решение какой провод отключить от схемы красный или синий. Правильный ответ заранее ни кому не известен. Точнее, правильный ответ выбирается случайным образом. Если время истекло — игрок проиграл, если выдернут не тот провод, игрок проиграл. Если игрок отключил провод, выбранный программой как правильный — игрок выиграл. 

За обработку логики игры «Красный или синий»  будет отвечать микроконтроллер на плате Arduino. Электронная схема для игры «Красный или синий» может содержать два сигнальных светодиода и два провода красный и синий, вставленных в гнёзда макетной платы.

Если же мы, вместо светодиодов для обратной связи с игроком, будем использовать текстовый дисплей, то игра получится более привлекательной.

В нашем кружке электроники и робототехники в наличии оказался символьный дисплей MT16S2H отечественного производства. Для упрощения интерфейса связи дисплея с микроконтроллером, мы соединили интерфейсные выводы этого дисплея с микросхемой CN74HC595B1. Микросхема CN74HC595B1 это сдвиговый регистр с защёлкой. Эта микросхема очень часто используется для преобразования последовательного интерфейса в параллельный. 

Управление дисплеем MT16S2H осуществляется с помощью 8- битной (DB0...DB7) или 4-битной (DB4...DB7) шины данных и двух линий управления (RS, E). См. рис. 1.

Микросхема CN74HC595B1 преобразует синхронный поток последовательных данных на входе SER в параллельные данные на своих выходах Q0...Q7. Для синхронной передачи данных по входу SER в микросхему CN74HC595B1 должны быть задействованы входы синхронизации SRCLK (вход тактовых импульсов) и RCLK  (строб передачи байта данных).

В связке, дисплея MT16S2H и микросхемы CN74HC595B1 получился двух-строчный, по 16 символов в каждой строке, дисплей с последовательным интерфейсом передачи данных.

Рис. 1. Схема подключения буквенно-цифрового индикатора МТ-16S2H к плате Arduino с помощью сдвигового регистра 74HC595B1.

Рис. 2. Макет игры «Красный или синий». 

Программу для игры будем писать в среде разработки Arduino. Для управления дисплеем из репозитория Arduino необходимо загрузить библиотеку LiquidCrystal_74HC595. 

В учебных целях, из операторов и функций меняющих линейный ход выполнения программы будем использовать только тернарный оператор языка C++. В данном случае, Arduino функция loop() не в счёт. Во первых, потому что, программу без функции loop() компилятор среды Arduino возвращает с ошибкой. Во вторых, потому что функция loop() придумана авторами Arduino для облегчения изучения языка C++ для микроконтроллеров, то есть для нашего случая.

Начнём поэтапно разрабатывать программу для нашей игры.

1. Организуем вывод на дисплей обратного счётчика секунд, начиная с 60-ой секунды.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x=60;

void setup() {
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
}

void loop() {
  lcd.setCursor(6, 1);
  lcd.print(x--);
  lcd.print(" ");
  delay(1000);
}

Скетч 1. Вывод на дисплей надписи „Красный или синий?”  в первой строке и обратного счётчика секунд во второй строке.

В скетче 1, прежде всего, с помощью директивы #include препроцессора языка C++ подключаем библиотеку LiquidCrystal_74HC595. Затем создаём объект lcd класса LiquidCrystal_74HC595. 

Прототип конструктора класса LiquidCrystal_74HC595 выглядит следующим образом:

LiquidCrystal_74HC595(SER, SRCLK, RCLK, RS, E, D4, D5, D6, D7);

Конструктор класса LiquidCrystal_74HC595  принимает в качестве первых трёх параметров номера цифровых портов на плате Arduino. На рис. 1 на принципиальной электрической схеме подключения индикатора МТ-16S2H к плате Arduino с помощью сдвигового регистра 74HC595B1 мы видим, что вход микросхемы 74HC595B1 SER подключён к цифровому порту 4, SRCLK подключён к цифровому порту 3, RCLK подключён к цифровому порту 2.

Оставшиеся 6 параметров конструктора класса LiquidCrystal_74HC595 это номера выходов сдвигового регистра 74HC595B1 подключённые ко входам RS, E, D4, D5, D6, D7 интерфейса дисплея МТ-16S2H.

Иначе, параметрами конструктора класса LiquidCrystal_74HC595 являются детали подключения сдвигового регистра 74HC595B1 на принципиальной электрической схеме дисплея, см. рис. 1.

В нашей программе будет необходим счётчик секунд, для этого мы создаём переменную x целого типа (int) c начальным значением 60:

int x = 60;

В функции setup(), с помощью метода begin() мы инициализируем параметра объекта lcd класса LiquidCrystal_74HC595:

lcd.begibn(16, 2)

Здесь

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;

void setup() {
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0) ? lcd.print(x--) : lcd.print("BaaaM");
  lcd.print(" ");
  delay(1000);
}

Скетч 2.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;
bool red;

void setup() {
  randomSeed(analogRead(0));
  red = random(2);
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
  lcd.print(red);              // Проверка случайного числа
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0) ? lcd.print(x--) : lcd.print("BaaaM");
  lcd.print(" ");
  delay(1000);
}

Скетч 3.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;
bool red;
int redPin = 7;                   // Подключаем красный провод на pin и на минус
int bluePin = 8;                  // Подключаем синий провод на pin и на минус

void setup() {
  pinMode(redPin, INPUT_PULLUP);  // Настраиваем pin как вход подтянутый на плюс
  pinMode(bluePin, INPUT_PULLUP); // Настраиваем pin как вход подтянутый на плюс
  randomSeed(analogRead(0));
  red = random(2);
  lcd.begin(16, 2);
  lcd.print(digitalRead(redPin));  // Проверка красного провода
  lcd.print("Red or Blue?");
  lcd.print(digitalRead(bluePin)); // Проверка синего провода
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0) ? lcd.print(x--) : lcd.print("BaaaM");
  lcd.print(" ");
  delay(1000);
}

Скетч 4.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;
int red;
int redPin = 7;                   // Подключаем красный провод на pin и на минус
int bluePin = 8;                  // Подключаем синий провод на pin и на минус

void setup() {
  pinMode(redPin, INPUT_PULLUP);  // Настраиваем pin как вход подтянутый на плюс
  pinMode(bluePin, INPUT_PULLUP); // Настраиваем pin как вход подтянутый на плюс
  randomSeed(analogRead(0));
  red = random(2);
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0 && !digitalRead(redPin) && !digitalRead(bluePin)) ? lcd.print(x--) : lcd.print("BaaaM");
  lcd.print("      ");
  delay(1000);
}

Скетч 5.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;
int red;
int redPin = 7;                   // Подключаем красный провод на pin и на минус
int bluePin = 8;                  // Подключаем синий провод на pin и на минус

void setup() {
  pinMode(redPin, INPUT_PULLUP);  // Настраиваем pin как вход подтянутый на плюс
  pinMode(bluePin, INPUT_PULLUP); // Настраиваем pin как вход подтянутый на плюс
  randomSeed(analogRead(0));
  red = random(2);
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0) ? lcd.print(x--) : lcd.print("BaaaM");
  x = (!digitalRead(redPin) && !digitalRead(bluePin)) ? x : -1;
  lcd.print("      ");
  delay(1000);
}

Скетч 6.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;
bool red;
int redPin = 7;                   // Подключаем красный провод на pin и на минус
int bluePin = 8;                  // Подключаем синий провод на pin и на минус

void setup() {
  pinMode(redPin, INPUT_PULLUP);  // Настраиваем pin как вход подтянутый на плюс
  pinMode(bluePin, INPUT_PULLUP); // Настраиваем pin как вход подтянутый на плюс
  randomSeed(analogRead(0));
  red = random(2);
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
  lcd.print(red);
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0) ? lcd.print(x--) : lcd.print("BaaaM");
  x = (digitalRead(redPin) && red) || (digitalRead(bluePin) && !red) ? -1 : x;
  lcd.print("      ");
  delay(1000);
}

Скетч 7.

#include <LiquidCrystal_74HC595.h>
LiquidCrystal_74HC595 lcd(4, 3, 2, 1, 2, 3, 4, 5, 6);

int x = 60;
bool red;
int redPin = 7;                   // Подключаем красный провод на pin и на минус
int bluePin = 8;                  // Подключаем синий провод на pin и на минус

void setup() {
  pinMode(redPin, INPUT_PULLUP);  // Настраиваем pin как вход подтянутый на плюс
  pinMode(bluePin, INPUT_PULLUP); // Настраиваем pin как вход подтянутый на плюс
  randomSeed(analogRead(0));
  red = random(2);
  lcd.begin(16, 2);
  lcd.print("Red or Blue?");
  //lcd.print(red);               // // Проверка случайного числа
}

void loop() {
  lcd.setCursor(6, 1);
  (x >= 0) ? lcd.print(x--) : lcd.print("BaaaM");
  x = (!digitalRead(redPin) && !digitalRead(bluePin)) ? x : 0;
  x = (digitalRead(redPin) && red) || (digitalRead(bluePin) && !red) ? -1 : x;
  lcd.print("      ");
  delay(1000);
}

Скетч 8.