Освой Arduino играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Популярная игра на запоминание последовательностей. Загорается серия светодиодов, вам нужно повторить серию. Серия начинается с одной вспышки, затем серия увеличивается на единицу. Если сбились, то всё начинается сначала.
Для игры понадобятся четыре кнопки и четыре светодиода. Очень хорошо, если светодиоды будут разного цвета: красный, зелёный, жёлтый и синий. Добавим также пищалку для звуковых эффектов.
Схема.
Код не слишком аккуратный, его ещё стоит причесать. Это предварительный набросок, чтобы убедиться в работоспособности проекта.
#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;
}
Короткий ролик, в котором я постарался быстрее ошибиться, чтобы не затягивать видео.