Menu
CoddyTech

Игра на реакцию: фальстарт

Часть раздела Проекты путешествия по Arduino на Coddy. Урок 7 из 24.

Сейчас хитрый игрок может жульничать: многократно нажимать во время ожидания, и одно из нажатий придётся сразу после включения света. В гонках для этого есть правило: движение до сигнала считается фальстартом, и старт отменяется.

Конечный автомат уже знает, когда игрок нажимает слишком рано: при любом нажатии в состоянии WAITING. Проверяй это там, до проверки времени:

case WAITING:
  if (pressed) {
    Serial.println("Too soon!");
    state = READY;
  } else if (millis() - waitStart >= waitTime) {
    // зажгите светодиод, как и раньше
  }
  break;

Возврат в состояние READY завершает раунд: LED так и не загорается, а следующее нажатие начинает новую игру с новым случайным временем ожидания. При использовании delay(waitTime) плата вообще не смогла бы заметить это нажатие.

challenge icon

Задание

Средне

Обрабатывайте фальстарты:

  • в состоянии WAITING нажатие выводит Too soon! и возвращает программу в состояние READY, не включая светодиод
  • всё остальное остаётся как есть: следующее нажатие начинает новый раунд

Нажмите Run, попробуйте быстро нажать дважды, затем нажмите Check.

Попробуйте сами

const int ledPin = 12;
const int buttonPin = 2;

// Три состояния одного раунда
enum State { READY, WAITING, LIT };
State state = READY;

int lastButton = HIGH;       // предыдущее показание кнопки
unsigned long waitStart = 0; // когда началось ожидание
unsigned long waitTime = 0;  // сколько длится это ожидание
unsigned long litAt = 0;     // когда загорелся светодиод

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Press the button to start");
}

void loop() {
  int button = digitalRead(buttonPin);
  bool pressed = (button == LOW && lastButton == HIGH);  // кнопка только что нажата
  lastButton = button;
  unsigned long now = millis();

  switch (state) {
    case READY:
      if (pressed) {
        randomSeed(micros());  // время нажатия никогда не бывает одинаковым дважды
        waitTime = random(1000, 3001);
        waitStart = now;
        state = WAITING;
      }
      break;
    case WAITING:
      if (now - waitStart >= waitTime) {
        digitalWrite(ledPin, HIGH);
        litAt = now;
        state = LIT;
      }
      break;
    case LIT:
      if (pressed) {
        digitalWrite(ledPin, LOW);
        unsigned long reaction = now - litAt;
        Serial.print("Reaction: ");
        Serial.print(reaction);
        Serial.println(" ms");
        state = READY;
      }
      break;
  }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Проекты

Потренируйтесь самостоятельно: Песочница Arduino