Кнопочные ковбои
В этом эксперименте мы создаем игрушку на реакцию: кто быстрее нажмет кнопку по сигналу.
Список деталей для эксперимента
1 плата Arduino Uno
1 беспаечная макетная плата
2 тактовых кнопки
2 резистора номиналом 220 Ом
2 светодиода
1 пьезопищалка
10 проводов «папа-папа»
Принципиальная схема

Схема на макетке

Скетч
// p120_button_cowboys.ino
#define BUZZER_PIN 12 // пин с пищалкой
#define PLAYER_COUNT 2 // количество игроков-ковбоев
// вместо перечисления всех пинов по-одному, мы объявляем пару
// списков: один с номерами пинов с кнопками, другой — со
// светодиодами. Списки также называют массивами (англ. array)
int buttonPins[PLAYER_COUNT] = {3, 13};
int ledPins[PLAYER_COUNT] = {9, 11};
void setup()
{
pinMode(BUZZER_PIN, OUTPUT);
for (int player = 0; player < PLAYER_COUNT; ++player) {
// при помощи квадратных скобок получают значение в массиве
// под указанным в них номером. Нумерация начинается с нуля
pinMode(ledPins[player], OUTPUT);
pinMode(buttonPins[player], INPUT_PULLUP);
}
}
void loop()
{
// даём сигнал «пли!», выждав случайное время от 2 до 7 сек
delay(random(2000, 7000));
tone(BUZZER_PIN, 3000, 250); // 3 килогерца, 250 миллисекунд
for (int player = 0; ; player = (player+1) % PLAYER_COUNT) {
// если игрок номер «player» нажал кнопку...
if (!digitalRead(buttonPins[player])) {
// ...включаем его светодиод и сигнал победы на 1 сек
digitalWrite(ledPins[player], HIGH);
tone(BUZZER_PIN, 4000, 1000);
delay(1000);
digitalWrite(ledPins[player], LOW);
break; // Есть победитель! Выходим (англ. break) из цикла
}
}
}
Пояснения к коду
Массив состоит из элементов одного типа, в нашем случае
int
.Объявить массив можно следующими способами:
int firstArray[6]; // 6 целых чисел с неопределёнными начальными значениями int pwmPins[] = {3, 5, 6, 9, 10, 11}; // 6 целых чисел, длина вычисляется автоматом boolean buttonState[3] = {false, true, false}; // можно использовать элементы любого типа
Когда мы объявляем массив с указанием количества его элементов
n
, это число всегда на 1 больше, чем номер последнего элемента (n-1
), т.к. индекс первого элемента —0
.Считать или записать значение элемента массива можно, обратившись к нему по индексу, например
firstArray[2]
илиbuttonState[counter]
, гдеcounter
— переменная, такая как счетчик цикла.В переменных типа
long
можно хранить значения до 2 147 483 647.unsigned int
в этом случае нам будет недостаточно, потому что 65 535 миллисекунд пройдут чуть больше чем за минуту!Функция
random(min, max)
возвращает целое псевдослучайное число в интервале [min
,max
]. Для драматичности каждая игра начинается с паузы случайной длины.Благодаря массивам в этом эксперименте мы настраиваем порты, считываем кнопки и включаем светодиоды в циклах со счетчиком, который используется как индекс элемента.
Мы используем цикл
for
без условия его завершения, поэтому пока мы явно того не потребуем, цикл будет крутиться до бесконечности.Мы использовали выражение
player = (player+1) % PLAYER_COUNT
для счётчика цикла, чтобы не только увеличивать его на единицу каждый раз, но и обнулять при достижении последнего игрока.Инструкция
break
прекращает работу цикла и выполнение программы продолжается с инструкции после его конца.
Вопросы для проверки себя
Можно ли поместить в один массив элементы типа
boolean
иint
?Обязательно ли при объявлении массива заполнять его значениями?
Чем удобно использование массива?
Как обратиться к элементу массива, чтобы прочитать его значение?
Чем отличаются инструкции
continue
иbreak
?
Задания для самостоятельного решения
Сделайте напряженный вариант игры: пусть интервал между сигналами будет в диапазоне от 10 до 15 секунд.
В игре есть лазейка: кнопку можно зажать до сигнала «пли!» и таким образом сразу же выиграть. Дополните программу так, чтобы так выиграть было нельзя.
Добавьте в игру еще двух ковбоев!