/*
Arduino Simon Says Game (لعبة سيمون سايز للأردوينو) - 5 Colors
*/
// تعريف عدد الألوان (N)
#define NUM_COLORS 5
// تحديد مخارج الأزرار ومصابيح LED ومخارج الصوت (البَزَر)
const byte LED_PINS[NUM_COLORS] = { 3, 4, 5, 6,7}; // مخارج LEDs: 5 ألوان
const byte BUTTON_PINS[NUM_COLORS] = {9, 10, 11, 12, 13}; // مداخل الأزرار: 5 أزرار
#define BUZZER_PIN 8 // مخرج الجرس (Buzzer)
// ترددات النغمات لكل لون (5 نغمات مختلفة)
const int TONES[NUM_COLORS] = {262, 330, 392, 440, 494}; // نغمات C4, E4, G4, A4, B4
// طول التسلسل الأقصى
#define MAX_ROUNDS 30 // يمكن زيادة طول التسلسل لـ 30 جولة
byte gameSequence[MAX_ROUNDS]; // مصفوفة لتخزين تسلسل اللعبة
byte currentRound = 0; // عدد الجولات الناجحة
void setup() {
Serial.begin(9600);
// إعداد المخارج والمداخل
for (int i = 0; i < NUM_COLORS; i++) {
pinMode(LED_PINS[i], OUTPUT);
pinMode(BUTTON_PINS[i], INPUT); // نستخدم INPUT هنا لتوصيل Pull-Down كما هو موضح في المخطط
}
pinMode(BUZZER_PIN, OUTPUT);
// تهيئة مولد الأرقام العشوائية
randomSeed(analogRead(A0));
// إشارة بدء التشغيل
playStartSignal();
}
void loop() {
currentRound++; // زيادة طول التسلسل
// 1. إضافة خطوة عشوائية جديدة للتسلسل
if (currentRound <= MAX_ROUNDS) {
// توليد رقم عشوائي بين 0 و 4 (تشمل 0 و 4)
gameSequence[currentRound - 1] = random(0, NUM_COLORS);
} else {
// اللاعب فاز! (وصل إلى الحد الأقصى للجولات)
playWinnerSignal();
delay(5000);
currentRound = 0; // إعادة اللعبة
return;
}
Serial.print("Current Round: ");
Serial.println(currentRound);
// 2. عرض التسلسل بالكامل
displaySequence();
// 3. انتظار إدخال اللاعب والتحقق منه
if (checkUserSequence() == false) {
playLoserSignal(); // الإدخال خاطئ
currentRound = 0; // إعادة اللعبة من البداية
delay(2000);
} else {
playSuccessSignal(); // الإدخال صحيح
delay(1000);
}
}
// --------------------------- الدوال المساعدة ---------------------------
// عرض التسلسل الحالي من البداية
void displaySequence() {
for (int i = 0; i < currentRound; i++) {
int colorIndex = gameSequence[i];
lightLED(colorIndex);
delay(200);
}
}
// التحقق من إدخال اللاعب
bool checkUserSequence() {
for (int i = 0; i < currentRound; i++) {
int expectedButton = gameSequence[i];
int pressedButton = waitForButtonPress();
// إذا لم يضغط اللاعب على أي زر أو ضغط على زر خاطئ
if (pressedButton == -1 || pressedButton != expectedButton) {
return false;
}
}
return true;
}
// انتظار ضغطة زر
int waitForButtonPress() {
unsigned long startTime = millis();
while (millis() - startTime < 3000) { // اللاعب لديه 3 ثواني للضغط على الزر
for (int i = 0; i < NUM_COLORS; i++) {
// بما أننا نستخدم توصيل Pull-Down، يكون الزر مضغوطاً عندما تكون القيمة HIGH
if (digitalRead(BUTTON_PINS[i]) == HIGH) {
lightLED(i); // إضاءة الـ LED المقابل
while (digitalRead(BUTTON_PINS[i]) == HIGH); // انتظار تحرير الزر
delay(50);
return i; // إرجاع فهرس الزر المضغوط (0-4)
}
}
}
return -1; // مهلة، لم يتم الضغط على أي زر
}
// إضاءة LED وتشغيل نغمة
void lightLED(int index) {
digitalWrite(LED_PINS[index], HIGH);
tone(BUZZER_PIN, TONES[index], 200);
delay(200);
digitalWrite(LED_PINS[index], LOW);
noTone(BUZZER_PIN);
delay(50);
}
// إشارة بدء اللعبة
void playStartSignal() {
for (int i = 0; i < NUM_COLORS; i++) {
digitalWrite(LED_PINS[i], HIGH);
}
tone(BUZZER_PIN, 523, 500); // نغمة C5
delay(500);
for (int i = 0; i < NUM_COLORS; i++) {
digitalWrite(LED_PINS[i], LOW);
}
noTone(BUZZER_PIN);
delay(1000);
}
// إشارة النجاح (نغمة تصاعدية)
void playSuccessSignal() {
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, TONES[i] * 2, 80);
delay(80);
noTone(BUZZER_PIN);
}
}
// إشارة الخسارة (نغمة تنازلية أو متقطعة)
void playLoserSignal() {
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, 100, 200); // نغمة منخفضة للخسارة
delay(200);
noTone(BUZZER_PIN);
}
}
// إشارة الفوز الكامل
void playWinnerSignal() {
for (int i = 0; i < NUM_COLORS; i++) {
tone(BUZZER_PIN, TONES[i] * 3, 100);
delay(100);
noTone(BUZZER_PIN);
}
}