Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

دالة الاستدعاء الذاتي: العد التنازلي

جزء من قسم Logic & Flow في رحلة Dart على Coddy — الدرس 48 من 65.

حان الوقت الآن لوضع العودية (recursion) موضع التنفيذ باستخدام دالة عد تنازلي بسيطة. سيساعدك هذا التمرين على فهم كيفية عمل الحالة الأساسية (base case) والخطوة العودية (recursive step) معاً في كود حقيقي.

تبدأ دالة العد التنازلي برقم وتطبع كل رقم وصولاً إلى الصفر. إليك كيف تجعل العودية (recursion) هذا يعمل: إذا كان الرقم أكبر من الصفر، فاطبعه ثم استدعِ الدالة نفسها برقم أصغر. عندما يصل الرقم إلى الصفر، توقف.

void countdown(int number) {
  if (number <= 0) {
    print("Done!");
    return; // الحالة الأساسية - توقف هنا
  }
  
  print(number);
  countdown(number - 1); // الخطوة العودية
}

تتحقق الحالة الأساسية (base case) مما إذا كان number <= 0 - وهذا هو الوقت الذي نتوقف فيه عن استدعاء الدالة. تقوم الخطوة العودية (recursive step) باستدعاء countdown(number - 1)، وهي نفس المشكلة ولكن بمدخلات أصغر، مما يقربنا تدريجياً نحو الحالة الأساسية.

عندما تستدعي countdown(3)، فإنه يطبع 3، ثم يستدعي countdown(2)، الذي يطبع 2، ثم يستدعي countdown(1)، الذي يطبع 1، ثم يستدعي countdown(0)، الذي يطبع "Done!" ويتوقف.

challenge icon

التحدي

سهل

قم بإنشاء برنامج ينفذ مؤقت عد تنازلي تكراري (recursive) مع رسائل مخصصة. سيقوم برنامجك بتوضيح مفهوم التكرار (recursion) من خلال العد التنازلي من رقم معين وعرض رسائل مخصصة في كل خطوة.

  1. اقرأ مدخلاً نصياً يمثل رقم البداية للعد التنازلي
  2. اقرأ مدخلاً نصياً يمثل بادئة الرسالة المخصصة (مثلاً، "Launch in"، أو "Timer"، أو "Countdown")
  3. قم بتحويل المدخل الأول إلى عدد صحيح باستخدام int.parse()
  4. أنشئ دالة تكرارية تسمى customCountdown تأخذ معاملين:
    • عدد صحيح number يمثل قيمة العد التنازلي الحالية
    • سلسلة نصية messagePrefix لبادئة الرسالة المخصصة
  5. يجب أن تنفذ الدالة المنطق التالي:
    • الحالة الأساسية (Base case): إذا كان الرقم أقل من أو يساوي 0، اطبع "Countdown complete!" ثم قم بالإنهاء (return)
    • الخطوة التكرارية (Recursive step): اطبع بادئة الرسالة متبوعة بالرقم الحالي، ثم استدعِ الدالة نفسها مع number - 1
  6. استدعِ الدالة customCountdown مع الرقم المحول وبادئة الرسالة
  7. اعرض النتائج بالتنسيق الدقيق الموضح أدناه

على سبيل المثال، إذا كانت المدخلات هي "5" و "Launch in"، يجب أن يخرج برنامجك:

Starting countdown from: 5
Message prefix: Launch in
========================
Launch in 5
Launch in 4
Launch in 3
Launch in 2
Launch in 1
Countdown complete!

إذا كانت المدخلات هي "3" و "Timer"، يجب أن يخرج برنامجك:

Starting countdown from: 3
Message prefix: Timer
========================
Timer 3
Timer 2
Timer 1
Countdown complete!

إذا كانت المدخلات هي "0" و "Ready"، يجب أن يخرج برنامجك:

Starting countdown from: 0
Message prefix: Ready
========================
Countdown complete!

يجب أن ينفذ برنامجك الدالة التكرارية customCountdown التي تستدعي نفسها برقم متناقص حتى تصل إلى الحالة الأساسية. يجب أن تطبع الدالة الرسالة المخصصة مع الرقم الحالي في كل استدعاء تكراري، مما يوضح كيف يقوم التكرار (recursion) بتفكيك المشكلة إلى مشكلات فرعية أصغر ومتطابقة. استخدم إدراج النصوص (string interpolation) لتنسيق رسائل العد التنازلي كـ "$messagePrefix $number".

ورقة مرجعية

توضح دالة العد التنازلي العودية كيفية عمل العودية من خلال العد التنازلي من رقم إلى الصفر:

void countdown(int number) {
  if (number <= 0) {
    print("Done!");
    return; // الحالة الأساسية - توقف هنا
  }
  
  print(number);
  countdown(number - 1); // الخطوة العودية
}

تتحقق الحالة الأساسية مما إذا كان number <= 0 لإيقاف العودية. تستدعي الخطوة العودية نفس الدالة مع number - 1، للتحرك نحو الحالة الأساسية.

عند استدعاء countdown(3)، فإنها تطبع 3 ← 2 ← 1 ← "Done!" من خلال إجراء استدعاءات عودية متتالية بقيم متناقصة.

جرّب بنفسك

import 'dart:io';

// TODO: قم بإنشاء دالة customCountdown الخاصة بك هنا
// تذكر معالجة الحالة الأساسية (الرقم <= 0) والخطوة التكرارية

void main() {
  // قراءة المدخلات
  String? startingNumber = stdin.readLineSync();
  String? messagePrefix = stdin.readLineSync();
  
  // تحويل النص إلى عدد صحيح
  int number = int.parse(startingNumber!);
  
  // عرض المعلومات الأولية
  print('Starting countdown from: $number');
  print('Message prefix: $messagePrefix');
  print('========================');
  
  // TODO: استدعِ دالة customCountdown الخاصة بك هنا
  // تذكر معالجة سلامة القيم الخالية (null safety) لـ messagePrefix
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Logic & Flow