الاستدعاء الذاتي
اكتب دالة باسم down تأخذ int واحدًا باسم n. إذا كان n يساوي 0 أو أقل، توقّف بـ return; فارغ. وإلا فاكتب n، ثم استدعِ down(n - 1) من داخل الدالة نفسها. من Main استدعِ down(3);. يجب أن تُظهر الشاشة ثلاثة أسطر: 3، ثم 2، ثم 1. الدالة تواصل استدعاء نفسها برقم أصغر حتى ينهي التوقف السلسلة. ذلك الاستدعاء الذاتي مع توقف هو ما تعلّمه هذه الصفحة. أبقِ اسم الفئة العامة Pine.
دالة تستدعي نفسها
في صفحة النطاق، شغّلت mark مرة واحدة وانتهت. هنا تعمل down، ثم تبدأ down أخرى بوسيط جديد قبل أن تكتمل الدعوة الأولى تمامًا. لكل استدعاء n خاص به. السلسلة تنتهي فقط عندما يصل استدعاء إلى التوقف.
افتح ملف Pine. اسم الفئة يبقى Pine. هذه الصفحة لا تعيد تسمية النوع. احذف أي عرض mark متبقٍ إن كان ذلك كل ما لديك في Main. احذف أي بقايا paint. احذف أي سطر ReadLine. الملف الذي تحتفظ به لا ينتظر الكتابة.
خارج Main، وما زلت داخل أقواس الفئة المعقوفة، اكتب static void down(int n). أبقِ void في هذه الصفحة: كل خطوة تكتب، ولا حاجة لعودة قيمة عبر return مكتوب النوع. التوقف يستخدم return; بلا قيمة — ينهي هذا الاستدعاء فقط. احفظ الملف قبل التشغيل. البرنامج الكامل الأول في الصندوق التالي.
الملف الذي تحتفظ به
هذه النسخة التي تشغّلها أولًا. Main يحمل استدعاءً واحدًا. down يحمل التوقف، وسطر الكتابة، والاستدعاء الذاتي.
using System;
public class Pine
{
public static void Main()
{
down(3);
}
static void down(int n)
{
if (n <= 0)
{
return;
}
Console.WriteLine(n);
down(n - 1);
}
}
اقرأ من الأعلى. using System; يجهّز أسماء قصيرة. public class Pine يسمّي النوع. public static void Main() حيث يبدأ وقت التشغيل. الاستدعاء down(3) يدخل وn يساوي 3. ذلك أكبر من 0، فتكتب الدالة 3، ثم تستدعي down(2). الاستدعاء الثاني يكتب 2، ثم يستدعي down(1). الاستدعاء الثالث يكتب 1، ثم يستدعي down(0). الاستدعاء بـ 0 يصطدم بـ n <= 0 ويعود دون كتابة. تنتهي السلسلة. ثلاثة أسطر على الشاشة: 3، ثم 2، ثم 1.
شغّله بـ dotnet run. البرنامج يكتب ثلاثة أسطر ويتوقف. لا ينتظر منك الكتابة. إن انتظر dotnet run، فما زال ReadLine في الملف. احذف ذلك السطر وأبقِ down(3); مع دالة down أعلاه. الشاشة تعرض 3، ثم 2، ثم 1. إن عرضت الشاشة 4 فقط، فما زال استدعاء mark(4) متبقيًا يعمل. إن عرضت الشاشة الحروف down، فسطر الكتابة فيه علامات اقتباس: Console.WriteLine("down");. لا تعيد تثبيت .NET SDK من أجل شاشة تعرض الأسطر الخطأ.
امشِ تشغيلًا كاملًا بالترتيب. C# يبدأ عند Main. الاستدعاء down(3) يدخل وn يساوي 3. ذلك أكبر من 0، فتكتب الدالة 3، ثم تستدعي down(2). الاستدعاء الثاني يكتب 2، ثم يستدعي down(1). الاستدعاء الثالث يكتب 1، ثم يستدعي down(0). الاستدعاء بـ 0 يصطدم بـ n <= 0 ويعود دون كتابة. تنتهي السلسلة. الشاشة تبقي الأسطر الثلاثة المكتوبة.
كل استدعاء من تلك الاستدعاءات مرور منفصل عبر نص الدالة نفسه. المرور الأول ما زال لديه عمل بعد بدء down(2) — أي الإنهاء بعد عودة الاستدعاء الداخلي. أنت لا تكتب أربعة أسماء دوال مختلفة. تكتب دالة واحدة وتدع الوسيط الأصغر يحمل التقدم نحو التوقف.
إن غيّرت البداية إلى down(2);، يجب أن تُظهر الشاشة 2 ثم 1. جسم الدالة يبقى نفسه؛ يتغيّر الوسيط الأول فقط، فتصبح السلسلة أقصر. البدء بـ down(4); يجب أن يُظهر أربعة أسطر: 4، 3، 2، 1. مرة أخرى الجسم بلا تغيير؛ فقط Main يختار القيمة الأولى.
ضع التوقف أولًا
يجب فحص التوقف قبل سطر الكتابة وقبل الاستدعاء الذاتي. إن كتبت أولًا ولم تختبر n أبدًا، أو استدعيت دائمًا down(n) بنفس القيمة، فالبرنامج لا ينتهي. أبقِ كتلة if (n <= 0) في أعلى الدالة في هذا الشكل للمبتدئين.
using System;
public class Pine
{
public static void Main()
{
down(2);
}
static void down(int n)
{
if (n <= 0)
{
return;
}
Console.WriteLine(n);
down(n - 1);
}
}
هذا هو الملف الثاني. يعلّم نفس الجسم ببداية أقصر. شغّل dotnet run. الشاشة تعرض 2 ثم 1. التوقف ما زال ينهي السلسلة عندما يصل n إلى 0. كتابة down(n) بدلًا من down(n - 1) ترسل الرقم نفسه مرارًا. عندها قد يعمل البرنامج حتى يوقفه النظام. الوسيط الأصغر جزء من الفكرة: كل استدعاء يجب أن يتحرك نحو التوقف.
تخيّل التوقف باب الخروج. سطر الكتابة هو العمل في هذه الخطوة. الاستدعاء الذاتي هو الخطوة التالية. إن غاب الباب، كل خطوة تفتح خطوة أخرى بلا نهاية. إن استخدمت الخطوة التالية نفس n، فأنت لا تسير نحو الباب. الخطآن يبدوان مختلفين في المصدر، لكن كليهما يرفضان الإنهاء النظيف في هذا الشكل للمبتدئين. بعد أن ترى 2 ثم 1، أعد ملف down(3) المحفوظ إن كان ذلك الشكل الذي تريد حفظه.
سلسلة الاستدعاء بجانب الشاشة
اقرأ استدعاء بداية واحدًا بجانب الأسطر التي يُنتجها. كل صف زيارة لـ down ما زالت تكتب.
📊 down call chain for down(3)
| Call | Value of n | Screen line |
|---|---|---|
first down(3) |
3 |
3 |
then down(2) |
2 |
2 |
then down(1) |
1 |
1 |
then down(0) |
0 |
(no line — stop) |
خلط شائع هو حذف التوقف. عندها كل استدعاء يكتب ويستدعي مجددًا إلى الأبد. خلط آخر هو الكتابة بعد الاستدعاء الذاتي بدلًا من قبله. في هذه الصفحة يأتي سطر الكتابة أولًا، فالشاشة تعدّ تنازليًا. إن نقلت Console.WriteLine تحت down(n - 1)، يتغيّر ترتيب الأسطر — أبقِ سطر الكتابة فوق الاستدعاء الذاتي للعدّ التنازلي المعروض هنا.
نطاق الصفحة السابقة ما زال مهمًا قليلًا: n لكل استدعاء هو معامل ذلك الاستدعاء. n في الاستدعاء الخارجي لا يعيد كتابة نفسه عندما يعمل الاستدعاء الداخلي. الاستدعاء الداخلي له n منفصل. عندما يعود الاستدعاء الداخلي، يستمر الخارجي من السطر بعد الاستدعاء الذاتي — وفي هذه الصفحة ذلك ببساطة نهاية الدالة.
عرض mark متبقٍ يمكن أن يبقى في نفس الملف ويُربك الشاشة إن استدعى Main ما زال mark. صفِّ Main إلى down(3); أو down(2); وأنت تتعلّم هذه الصفحة. لا تُعشّش down داخل أقواس Main المعقوفة. الدوال تجلس داخل الفئة، بجانب Main.
كتابة Console.WriteLine("down"); في Main تكتب كلمة down. لا تبدأ السلسلة. أبقِ down(3); عندما تريد أسطر العدّ التنازلي الثلاثة.
شكل آخر: التوقف لا يكتب شيئًا
رأيت بالفعل أن الاستدعاء بـ 0 يعود بهدوء. يمكنك أيضًا التمرين على قيمة بداية 1. يجب أن تُظهر الشاشة سطرًا واحدًا: 1. ثم الاستدعاء التالي down(0) الذي يتوقف.
using System;
public class Pine
{
public static void Main()
{
down(1);
}
static void down(int n)
{
if (n <= 0)
{
return;
}
Console.WriteLine(n);
down(n - 1);
}
}
هذا هو الملف الثالث. شغّل dotnet run. الشاشة تعرض سطرًا واحدًا: 1. نفس جسم الدالة يغطي down(3) وdown(2) وdown(1). يتغيّر الوسيط الأول في Main فقط. ذلك يكفي لهذه الصفحة للمبتدئين. أفكار أعمق مثل إرجاع مجموع من الاستدعاء الذاتي تنتظر دورات لاحقة؛ هنا الهدف هو الاستدعاء الذاتي، والوسيط الأصغر، والتوقف.
إن لم تُظهر الشاشة شيئًا إطلاقًا، تحقق مما إذا كان Main ما زال يستدعي شيئًا آخر، أو مما إذا كان اختبار التوقف خاطئًا — مثلًا if (n >= 0) يتوقف قبل أي كتابة عندما تبدأ بـ n موجب. أبقِ n <= 0 مخرجًا هادئًا، وأبقِ بداية موجبة في Main حتى يظهر سطر واحد على الأقل.
يمكنك كتابة down(int n)، والتوقف عندما يكون n يساوي 0 أو أقل، وكتابة n، ثم استدعاء down(n - 1). من Main، استدعاء واحد يبدأ السلسلة كلها. الشاشة تعرض أسطر العدّ التنازلي. دالة لا تتحرك أبدًا نحو التوقف لا تنتهي. الصفحة التالية هي classes، حيث تبدأ بناء الأنواع بحقول أبعد من صفحات الدوال static هذه.
الشاشة تحتفظ بالعدّ التنازلي
الملف الذي تحتفظ به يكتب 3، ثم 2، ثم 1، عندما يستدعي Main الأمر down(3);. الاستدعاء الذاتي داخل down، وحروف down ليست على الشاشة كتسمية مطبوعة إلا إذا وضعتها بين علامات اقتباس. تعشيش down داخل Main ليس الشكل الذي يبنيه هذا الدرس.
🧠 اختبر معرفتك
اختبر معرفتك
تحدى نفسك مع هذا الاختبار التفاعلي واكتشف مدى فهمك للموضوع
📝 التعليمات
- اقرأ كل سؤال بعناية
- اختر أفضل إجابة لكل سؤال
- يمكنك إعادة الاختبار عدة مرات كما تريد
- سيتم عرض تقدمك في الأعلى