
جافا - الأقراص والأعمدة (مثال)
| السلام عليكم و رحمة الله و بركاته
الأخ صوت الشباب الفاضل أحضر هذا الكود، وطلب منّي أن أشرحه، وهنا أقوم بذلك وأتمنى أن يستفيد منه وكذلك أنتم إن شاء الله :) ----------------------------- أول شي دعوني أوضّح الهدف من البرنامج. فهو
لعبة الأعمدة المشهورة. الفكرة ستكون على اعتبار أحد الأعمدة بداية الحركة، وآخر نهاية الحركة، وسيكون الثالث هو العمود المؤقت لدينا الذي سنستخدمه لوضع الأقراص مؤقتاً ريثما ننقلها. لنحل هذا علينا أن نستمر في التبديل بين مصدر الحركة والعمود المؤقت وعمود النهاية. سأقوم بتتبع حركة البرنامج مع توضيح قيم كل متغير في كل مرحلة من مراحل التشغيل. -----------------------------
----------------------------- يبدأ البرنامج في السطر العاشر بقراءة عدد الأقراص من المستخدم، ولنفترض أننا قمنا بإدخال القيمة 3 هكذا:
ثم يقوم بتشغيل الوظيفة doHanoi بتمرير أربعة قيم لها عدد الأقراص، والقيمة واحد والقيمة ثلاثة والقيمة اثنان. لنلقِ نظرة على كود الدالة نفسها، وكيف تنتقل القيم إليها:
أي أنه عند تشغيل الوظيفة method في المرة الأولى، تكون القيم الممررة هي: المرحلة البيضاء:
نلاحظ عند الدخول إلى الوظيفة أن أول سطر هو أداة (if) الشرطية، حيث يتأكّد من أن عدد الأقرص أكبر من أو يساوي الواحد، وفي حالتنا عدد الأقراص كان 3، سيقوم بالدخول وتنفيذ السطر 18 وهو نداء للوظيفة نفسها وهو ما يعرف بالـ Recursion في البرمجة، ولكن بقيم جديدة. من المهم جداً هنا أن نلاحظ أننا لم نكمل تشغيل النداء الأول للوظيفة، بل توقفنا عند السطر الثامن عشر. ثم قمنا بنداء الدالة مرة أخرى بقيم جديدة. لننظر إلى القيم الممرة الآن:
وتكون القيم الممررة في المرحلة الزرقاء كالتالي:
عند دخول الوظيفة سنجد الأداة الشرطية مرة أخرى، والقيمة لازالت تحقق الشرط (عدد الأقراص أكبر من أو يساوي الواحد). عند الدخول، سنجد نداءً جديداً لنفس الدالة، ونلاحظ أننا توقفنا عند السطر الثامن عشر مرة أخرى، ونادينا الوظيفة من جديد بالقيم الجديدة الزرقاء هكذا:
وتكون القيم الممررة في المرحلة الوردية كالتالي:
عند دخول الوظيفة سنجد الأداة الشرطية مرة أخرى، والقيمة لازالت تحقق الشرط (عدد الأقراص أكبر من أو يساوي الواحد). عند الدخول، سنجد نداءً جديداً لنفس الدالة، ونلاحظ أننا توقفنا عند السطر الثامن عشر مرة أخرى، ونادينا الوظيفة من جديد بالقيم الجديدة الوردية هكذا:
الآن القيم الممرة في المرحلة الصفراء ستكون كالتالي:
الأداة الشرطية في المرحلة الصفراء لا تتحقق، لأن عدد الأقراص = صفراً، والصفر ليست أكبر من ولا تساوي الواحد، لذا سيعود إلى السطر التاسع عشر من المرحلة الوردية، وسيقوم بطباعة القيم الموجودة في (start) و (end) في المرحلة الوردية كما يلي:
وهذا يعني أننا نقلنا القرص الموجود في أعلى العمود الأول إلى العمود الثالث، هكذا:
ثم سيتابع للسطر العشرون في المرحلة الوردية، سنجد أننا نستدعي نفس الوظيفة مرة أخرى، ولكن بقيم جديدة هكذا:
وستكون القيم في هذه المرحلة الخضراء هكذا:
ولكن كما ترون فإن الشرط لن يتحقق في هذه الحالة لأن عدد الأقراص = صفر، بالتالي ستكون المرحلة الوردية قد انتهت ولا أسطر جديدة، وهكذا سيعود إلى السطر التاسع عشر من المرحلة الزرقاء، وسيكون طباعة القيم في المرحلة الزرقاء، ودعوني أذكركم بها:
وهذا يعني أننا نقلنا القرص الموجود في أعلى العمود الأول إلى العمود الثاني هكذا:
الآن سيقوم بالانتقال للسطر العشرون من المرحلة الزرقاء، وسيكون كما يلي:
عدد الأقراص في هذه الحالة يحقق الشرط، وبالتالي سيقوم بالدخول إلى محتوى أداة الشرط (إذا) (وهذه هي المرحلة البنفسجية) وهنا سيحاول أن ينادي الوظيفة بعدد الأقراص 1-1=0 ولا حاجة لإعادة ما ذكرناه في السابق من أن هذا لن يحقق الشرط، وبالتالي سيقوم بتنفيذ السطر التالي وهو علامة الطباعة على القيم التي ستكون في هذه المرحلة البنفسجية كالتالي:
وهذا يعني أننا قمنا بنقل القرص الموجود في أعلى العمود الثالث إلى العمود الثاني، هكذا:
وهنا نكون قد وصلنا للسطر العشرون من المرحلة البنفسجية، ولا حاجة لإعادة ما ذكرناه لأن الدالة لن يتم تشغيلها فعدد الأقراص يساوي صفراً، وهكذا تنتهي المرحلة البنفسجية التي كانت تنفيذ آخر سطر في المرحلة الزرقاء، وهذا يعني أن الزرقاء أيضاً انتهت، وفي هذه الحالة سنعود للسطر التاسع عشر من المرحلة البيضاء، ودعوني أذكركم بالقيم في المرحلة البيضاء:
وهذا يعني أننا نقلنا القرص من أعلى العمود الأول إلى العمود الثالث:
ثم ننتقل إلى السطر العشرون في المرحلة البيضاء وهو يقوم بنداء نفس الوظيفة بالقيم التالية وهكذا نكون قد انتقلنا إلى مرحلة جديدة، وستكون مرحلة اللون البرتقالي:
وهكذا ستكون القيم الجديدة للمرحلة البرتقالية كالتالي:
تحقق الشرط وبالتالي سيتم استدعاء الوظيفة بالقيم الجديدة مرة أخرى في السطر الثامن عشر من المرحلة البرتقالية، هكذا:
ونكون قد انتقلنا إلى المرحلة الرمادية، وتكون المتغيرات في هذه المرحلة كما يلي:
في السطر الثامن عشر من المرحلة الرمادية لن يتم تشغيل الوظيفة لأن القيمة 1-1=0 وبالتالي لن يتم تحقق الشرط، وهكذا سنعود للسطر التاسع عشر من المرحلة الرمادية، والتي سيتم فيها طباعة القيم في المرحلة الرمادية هكذا:
وهذا يعني أنه سيتم نقل قرص من أعلى العمود الثاني إلى العمود الأول هكذا:
الآن سنتابع إلى السطر العشرون من المرحلة الرمادية، وهو أيضاً لن يفعل شيئاً لأن الشرط لن يتحقق، وهكذا سنعود إلى السطر التاسع عشر من المرحلة البرتقالية وسنطبع القيم الموجودة في المرحلة البرتقالية كما يلي:
وهذا يعني أننا قمنا بنقل قرص من العمود الثاني إلى العمود الثالث هكذا:
الآن وصلنا للسطر الأخير من المرحلة البرتقالية، التي بنهايتها تنتهي المرحلة البيضاء والبرنامج، وتشغيل هذه المرحلة سأتركه لكم :) تذكر أن عدد الأقراص يمكن أن يكون أكثر من ثلاثة، حاول أن تقوم بتتبع البرنامج في حالة عدد الأقراص كان اثنين أو أربعة أو أكثر. قد يساعدك على فهم الـ Recursion الشكل التالي:
إذ أننا حين نستدعي نفس الوظيفة من داخلها، نكون كأننا نشغلها من البداية لقيم جديدة ولابد أن تنتهي من التشغيل الثاني حتى تعود إلى نقطة ما بعد استدعاء الدالة نفسها. أرجو أن يكون المثال واضحاً، وشكراً لصوت الشباب الذي أحضره لي لأشرحه :) مع تحياتي |