Кнопочные ковбои
В этом эксперименте мы создаем игрушку на реакцию: кто быстрее нажмет кнопку по сигналу.
Список деталей для эксперимента
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 секунд.
В игре есть лазейка: кнопку можно зажать до сигнала «пли!» и таким образом сразу же выиграть. Дополните программу так, чтобы так выиграть было нельзя.
Добавьте в игру еще двух ковбоев!