Cześć!
Przerobiłem niedawno pierwszą część kursu arduino z tej strony i zdecydowałem, że sprawdzę się robiąc coś po swojemu. Zainspirował mnie tweet, podany przez arduino gdzie ktoś zrobił coś podobnego. Chodzi o prostą grę ćwiczącą pamięć znaną np. pod nazwą Simon. Gra polega na odtwarzaniu sekwencji kolorów wygenerowanych automatycznie przez komputer. Generalnie są 3 tryby. W pierwszym komputer losuje ciąg kolorów i w każdej kolejnej rundzie począwszy od pierwszej wyświetla ten ciąg graczowi o jeden kolor dłuższy. W drugim trybie jedna osoba wpisuje ciąg a druga ma go powtórzyć. W trzecim jest jak w pierwszym tylko nie można zastanawiać się dłużej niż sekundę pomiędzy kolorami. A skoro już to zrobiłem to wrzucam na forum, może ktoś uzna to za interesujące. Prawdopodbnie zmienianie trybów dałoby się zrobić lepiej bo teraz jest tak, że tryb można zmienić tylko podczas wpisywania ciągu. Poniżej jak to wygląda:
Kod na arduino create
/*
* Memory Game aka Simon Says
*/
#define REP(a, b) for (int (a) = 0; (a) < (b); ++(a))
#define FOR_PINS(a, b) for (int pin = (a); pin <= (b); ++pin)
#define MODE_BTN 2
#define LED_BEGIN 3
#define LED_END 6
#define BTN_BEGIN 7
#define BTN_END 10
#define LED_COUNT 4
#define MAX_SEQ_LEN 250
#define MODES 3
#define SP_MODE 0
#define P2_MODE 1
#define P4_MODE 2
bool turnedOn[LED_COUNT];
int seq[MAX_SEQ_LEN];
int level = 1;
int mode = 0;
void setup() {
randomSeed(analogRead(A0));
pinMode(MODE_BTN, INPUT_PULLUP);
FOR_PINS(LED_BEGIN, LED_END) pinMode(pin, OUTPUT);
FOR_PINS(BTN_BEGIN, BTN_END) pinMode(pin, INPUT_PULLUP);
gameInit();
}
void gameInit() {
REP(i, MAX_SEQ_LEN) seq[i] = random(LED_BEGIN, LED_END+1);
level = 1;
}
bool isPushedDown(int pin) {
return digitalRead(pin) == LOW;
}
void readInput() {
FOR_PINS(BTN_BEGIN, BTN_END) {
int led = pin - BTN_BEGIN;
turnedOn[led] = isPushedDown(pin);
}
}
int readBtnTimeout(unsigned long timeout) {
unsigned long startTime = millis();
while (millis()-startTime < timeout) {
readInput();
if (isPushedDown(MODE_BTN)) {
return MODE_BTN;
}
REP(i, LED_COUNT) {
if (turnedOn[i]) {
return i + BTN_BEGIN;
}
}
}
return -1;
}
int readBtn() {
return readBtnTimeout((unsigned long) 1000000);
}
bool readSequence() {
int btn = readBtn();
level = 0;
while (btn != -1) { // timeout
if (btn == MODE_BTN) {
changeMode();
return false;
}
int led = btn-LED_COUNT;
seq[level++] = led;
blinkLed(led);
btn = readBtnTimeout(1000);
}
return true;
}
void checkSequenceTimeout(unsigned long timeout) {
REP(i, level) {
int btn = -1;
if (i == 0) btn = readBtn();
else btn = readBtnTimeout(timeout);
if (btn == MODE_BTN) {
changeMode();
return;
}
int led = btn-LED_COUNT;
blinkLed(led);
if (led != seq[i] || btn == -1) {
failure(seq[i]);
return;
}
}
success();
}
void checkSequence() {
checkSequenceTimeout((unsigned long) 1000000);
}
void success() {
blinkAllLeds();
level = min(MAX_SEQ_LEN, level+1);
}
void failure(int led) {
blinkAllLeds();
REP(i, 3) {
blinkLedDelay(led, 150);
delay(100);
}
gameInit();
}
void playSequence() {
REP(i, level) {
blinkLed(seq[i]);
delay(100);
}
}
void blinkLedDelay(int pin, int duration) {
digitalWrite(pin, HIGH);
delay(duration);
digitalWrite(pin, LOW);
}
void blinkLed(int pin) {
blinkLedDelay(pin, 400);
}
void setLedsHigh() {
FOR_PINS(LED_BEGIN, LED_END) digitalWrite(pin, HIGH);
}
void setLedsLow() {
FOR_PINS(LED_BEGIN, LED_END) digitalWrite(pin, LOW);
}
void blinkAllLeds() {
setLedsHigh();
delay(200);
setLedsLow();
}
void wave() {
setLedsHigh();
delay(50);
REP(i, 3) FOR_PINS(LED_BEGIN, LED_END) {
analogWrite(pin, 30);
delay(65);
digitalWrite(pin, HIGH);
}
delay(50);
setLedsLow();
delay(800);
}
void changeMode() {
mode = (mode + 1) % MODES;
blinkLed(LED_BEGIN + mode);
gameInit();
}
void loop() {
wave();
switch (mode) {
case SP_MODE:
playSequence();
checkSequence();
break;
case P2_MODE:
if (readSequence()) {
blinkAllLeds();
checkSequence();
}
break;
case P4_MODE:
playSequence();
checkSequenceTimeout((unsigned long) 1000);
break;
};
}
Pozdrawiam 🙂