Освой Arduino играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Simon says Game

Популярная игра на запоминание последовательностей. Загорается серия светодиодов, вам нужно повторить серию. Серия начинается с одной вспышки, затем серия увеличивается на единицу. Если сбились, то всё начинается сначала.

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

Схема.

Simon schema

Код не слишком аккуратный, его ещё стоит причесать. Это предварительный набросок, чтобы убедиться в работоспособности проекта.


#define STATE_INTRO 0
#define STATE_TALKING 1
#define STATE_LISTENING 2
#define STATE_PROCESSING 3

// светодиоды
const int redLed = 2;
const int yellowLed = 3;
const int greenLed = 4;
const int blueLed = 5;

// кнопки
const int redButton = 13;
const int yellowButton = 12;
const int greenButton = 11;
const int blueButton = 10;

// пищалка
const int speaker = 7;

const int tones[] = { 220, 247, 196, 145 };

const int leds[] = {2, 3, 4, 5};
const int buttons[] = {13, 12, 11, 10};

const int MAX = 99;

int introCount = 0; // число проигрышей заставки
int buttonPressed = 0;
int gameTable[MAX];
int gameCount = -1;
int gameState = STATE_INTRO;
int listenCount = -1;

void setup() {
  Serial.begin(9600);
  pinMode(redLed, OUTPUT);
  pinMode(yellowLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(blueLed, OUTPUT);

  pinMode(redButton, INPUT);
  pinMode(yellowButton, INPUT);
  pinMode(greenButton, INPUT);
  pinMode(blueButton, INPUT);
  pinMode(speaker, OUTPUT);
  randomSeed(analogRead(0));
}

void loop() {
  switch (gameState) {
    case STATE_INTRO:
      intro();
      break;
    case STATE_TALKING:
      delay(1000);
      talk();
      break;
    case STATE_LISTENING:
      checkPress(redButton, redLed);
      checkPress(yellowButton, yellowLed);
      checkPress(greenButton, greenLed);
      checkPress(blueButton, blueLed);
      break;
    case STATE_PROCESSING:
      process();
      break;
  }
}

// вступление перед игрой
void intro() {
  // включаем по очереди все светодиоды со звуком
  for (int i = 0; i < 4; i++) {
    toneLight(leds[i], i);
    delay(20);
  }

  if (introCount++ == 2) {
    gameState = STATE_TALKING; // переключаемся в игру
    introCount = 0;
    seedGame();
  }
}

void toneLight(int led, int key) {
  digitalWrite(led, HIGH);
  tone(speaker, tones[key], 200);
  delay(200);
  digitalWrite(led, LOW);
}

void seedGame() {
  for (int i = 0; i < MAX; i++) {
    gameTable[i] = random4() + 0;
    //Serial.print(gameTable[i]); // последовательность
  }
}

void talk() {
  gameCount += 1;

  for (int i = 0; i < gameCount + 1; i++) {
    toneLight(leds[gameTable[i]], gameTable[i]);
    delay(200);
  }
  gameState = STATE_LISTENING;
}

void checkPress(int btn, int led) {
  int state = digitalRead(btn);
  if (state == HIGH) {
    toneLight(led, led - 2);
    buttonPressed = led - 2;
    gameState = STATE_PROCESSING;
    listenCount += 1;
    //Serial.println(listenCount);
  } else
    digitalWrite(led, LOW);
}

void process() {
  if (buttonPressed == gameTable[listenCount]) {
    gameState = STATE_LISTENING;

    if (listenCount == gameCount) {
      listenCount = -1;
      gameState = STATE_TALKING;
    } else {
      gameState = STATE_LISTENING;
      return;
    }
  } else {
    gameState = STATE_INTRO;
    gameCount = -1;
    listenCount = -1;
  }
}

int random4() {
  int r = random(4);
  return r;
}

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

Реклама