עוד
עוד
// Simon Game עבור PCB עם 4 כפתורים ו-4 לדים
// Buzzer: 8
// LEDs: 9 (צהוב), 10 (אדום), 11 (ירוק), 12 (כחול)
// Buttons: 2 (צהוב), 3 (אדום), 4 (ירוק), 5 (כחול)
#define BUZZER_PIN 8
const byte NUM_COLORS = 4;
const byte ledPins[NUM_COLORS] = {9, 10, 11, 12};
const byte buttonPins[NUM_COLORS] = {2, 3, 4, 5};
// מקסימום אורך רצף (שלבים)
const byte MAX_STEPS = 50;
// כאן נשמור את הרצף של המשחק
byte sequence[MAX_STEPS];
byte currentLength = 1; // מתחילים עם אורך 1
void setup() {
Serial.begin(115200);
// הגדרת פינים של לדים
for (byte i = 0; i < NUM_COLORS; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
// הגדרת פינים של כפתורים כ-INPUT_PULLUP (לחיצה = LOW)
for (byte i = 0; i < NUM_COLORS; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
// אקראיות לרצף
randomSeed(analogRead(A0));
generateSequence();
startAnimation();
}
// לולאת המשחק הראשית
void loop() {
// הצגת הרצף לשחקן
playSequence();
// קבלת תשובה מהשחקן
bool correct = getPlayerSequence();
if (correct) {
// הצלחה – צפצוף קצר ונגדיל את אורך הרצף
successTone();
if (currentLength < MAX_STEPS) {
currentLength++;
}
delay(800);
} else {
// טעות – צליל כישלון, אתחול אורך הרצף ל-1
failureTone();
currentLength = 1;
delay(1000);
}
}
/*** פונקציות עזר ***/
// יצירת רצף אקראי לכל המשחק (עד MAX_STEPS)
void generateSequence() {
for (byte i = 0; i < MAX_STEPS; i++) {
sequence[i] = random(NUM_COLORS); // ערך בין 0 ל-3
}
}
// הצגה נחמדה בתחילת המשחק
void startAnimation() {
for (int r = 0; r < 3; r++) {
for (byte i = 0; i < NUM_COLORS; i++) {
digitalWrite(ledPins[i], HIGH);
tone(BUZZER_PIN, 500 + i * 100, 80);
delay(100);
digitalWrite(ledPins[i], LOW);
}
}
delay(500);
}
// הצגת הרצף עד האורך הנוכחי
void playSequence() {
Serial.print("Showing sequence, length = ");
Serial.println(currentLength);
delay(500);
for (byte i = 0; i < currentLength; i++) {
byte colorIndex = sequence[i];
playColor(colorIndex, 400);
delay(200);
}
}
// ניגון צבע אחד (LED + צליל)
void playColor(byte index, int duration) {
// תדר שונה לכל צבע (סתם בשביל כיף)
int freq;
switch (index) {
case 0: freq = 440; break; // צהוב
case 1: freq = 494; break; // אדום
case 2: freq = 523; break; // ירוק
case 3: freq = 587; break; // כחול
default: freq = 440; break;
}
digitalWrite(ledPins[index], HIGH);
tone(BUZZER_PIN, freq, duration);
delay(duration);
digitalWrite(ledPins[index], LOW);
noTone(BUZZER_PIN);
}
// קבלת רצף מהשחקן, החזרה true אם הכל נכון, אחרת false
bool getPlayerSequence() {
Serial.println("Waiting for player input...");
for (byte i = 0; i < currentLength; i++) {
byte expected = sequence[i];
byte pressed = waitForButtonPress(); // מחכה עד לחיצה חוקית
Serial.print("Expected: ");
Serial.print(expected);
Serial.print(" Got: ");
Serial.println(pressed);
// ננגן את הצבע שהשחקן לחץ (פידבק מיידי)
playColor(pressed, 250);
if (pressed != expected) {
return false; // טעות
}
}
return true; // השחקן חזר על כל הרצף בהצלחה
}
// פונקציה שמחכה עד שלוחצים על אחד הכפתורים
// ומחזירה את האינדקס של הכפתור (0..3)
byte waitForButtonPress() {
while (true) {
for (byte i = 0; i < NUM_COLORS; i++) {
// לחיצה = LOW בגלל INPUT_PULLUP
if (digitalRead(buttonPins[i]) == LOW) {
// דיבאונס קטן
delay(20);
if (digitalRead(buttonPins[i]) == LOW) {
// מחכים לשחרור הכפתור
while (digitalRead(buttonPins[i]) == LOW) {
delay(10);
}
delay(50); // עוד קצת דיבאונס
return i;
}
}
}
}
}
// צליל הצלחה קצר
void successTone() {
tone(BUZZER_PIN, 800, 200);
delay(220);
tone(BUZZER_PIN, 1000, 200);
delay(250);
noTone(BUZZER_PIN);
}
// צליל כישלון
void failureTone() {
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, 200, 300);
for (byte j = 0; j < NUM_COLORS; j++) {
digitalWrite(ledPins[j], HIGH);
}
delay(300);
noTone(BUZZER_PIN);
for (byte j = 0; j < NUM_COLORS; j++) {
digitalWrite(ledPins[j], LOW);
}
delay(200);
}
}