Menu
CoddyTech

Trò chơi phản xạ: Khởi động sớm

Thuộc phần Dự án trong hành trình Arduino của Coddy. Bài học 7 trên 24.

Hiện tại, người chơi tinh quái có thể gian lận: nhấn liên tục trong lúc chờ, rồi một lần nhấn sẽ rơi đúng ngay sau khi đèn bật. Các cuộc đua có quy tắc xử lý việc này: di chuyển trước hiệu lệnh là xuất phát sớm, và lượt bắt đầu sẽ bị hủy.

Máy trạng thái đã biết khi nào người chơi nhấn quá sớm: bất kỳ lần nhấn nào trong trạng thái WAITING. Hãy kiểm tra tại đó, trước khi kiểm tra đồng hồ:

case WAITING:
  if (pressed) {
    Serial.println("Too soon!");
    state = READY;
  } else if (millis() - waitStart >= waitTime) {
    // Bật đèn LED như trước
  }
  break;

Quay lại READY sẽ kết thúc lượt chơi: đèn LED không bao giờ bật, và lần nhấn tiếp theo sẽ bắt đầu trò chơi mới với thời gian chờ ngẫu nhiên mới. Với delay(waitTime), bo mạch sẽ không thể nhận biết lần nhấn này.

challenge icon

Thử thách

Trung bình

Phát hiện lần nhấn quá sớm:

  • ở WAITING, khi bạn nhấn nút, chương trình in ra Too soon! rồi quay lại READY mà không bật đèn LED
  • mọi thứ khác vẫn giữ nguyên: lần nhấn tiếp theo bắt đầu vòng mới

Nhấn Chạy, thử nhấn nút hai lần thật nhanh, rồi nhấn Kiểm tra.

Tự làm thử

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

// Ba trạng thái của một lượt
enum State { READY, WAITING, LIT };
State state = READY;

int lastButton = HIGH;       // Trạng thái của nút ở lần đọc trước
unsigned long waitStart = 0; // Thời điểm bắt đầu chờ
unsigned long waitTime = 0;  // Thời gian chờ của lượt này
unsigned long litAt = 0;     // Thời điểm đèn LED sáng

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);  // Vừa được nhấn
  lastButton = button;
  unsigned long now = millis();

  switch (state) {
    case READY:
      if (pressed) {
        randomSeed(micros());  // Thời điểm nhấn không bao giờ trùng nhau giữa hai lần
        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 iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Dự án

Tự luyện tập: Playground Arduino