الحلقات التكرارية (Loops)

مقدمة

مشكلة تكرار الطباعة

تخيل أنك تريد كتابة كود يطبع اﻷعداد من 1 إلى 5، كيف سيكون شكل الكود؟ سأخمن ما ببالك اﻵن، سيكون كالتالي:

console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);

الكود السابق سيُنفذ، وسيطبع اﻷعداد من 1 إلى 5 ولا يوجد مشكلة، لكن ماذا لو أردنا طباعة اﻷعداد من 1 إلى 1000 ؟ وماذا لو أردنا طباعة اﻷعداد من 1 إلى 100000؟ بالتأكيد لن تتمكن من كتابة 100 ألف أمر طباعة!

مشكلة تكرار الجمع

لنفرض أني قلت لك اكتب برنامج يطبع مجموع اﻷعداد من 1 إلى 5.. بالتأكيد سيكون شكل الكود كالتالي:

console.log(1+2+3+4+5);

لكن لنفرض أني قلت لك اكتب برنامج يطبع مجموع اﻷعداد من 1 إلى 500! عملية صعبة على العقل البشري أكيد وأيضاً اﻷصعب أن تكتبهم كما في المثال السابق! خصوصا لو قلت لك نريد مجموع اﻷعداد من 1 إلى 100000! تحتاج لسنوات حتى تكتبهم كالمثال السابق..

مشكلة حقيقية

ومع ذلك المشكلات المطروحة باﻷعلى يمكن تنفيذها، من الممكن تضييع أيام في كتابة ألف أمر طباعة مثلاً.. ليس مستحيلاً؛ لكن هناك مشكلات أخرى بنفس الطريقة مستحيل أن تتمكن من حلها! كيف..؟

تخيل أنك تريد برمجة برنامج يقوم بتغيير أسماء كل الملفات الموجودة في مجلد معين على حاسوبك، في هذه المشكلة أنت لا تعلم كم سيكون عدد الملفات ! فهناك مجلدات فيها آلاف الملفات، وهناك فيها مئات، وهناك فيها عشرات الملفات! إذن كيف ستنفذها..؟ هل ستكتب 1000 أمر لتغيير أسماء الملفات؟ لنفرض أن الملفات كانوا فقط 5! ولنفرض أنهم كانوا 2000! إذن لا يمكنك حل هذه المشكلة ولو حتى ستمكث أيام تكرر في اﻷوامر وتكتب آلاف اﻷسطر!

وهنا يأتي دور الحلقات التكرارية لحل المشكلات السابقة بكل سهولة!

ما هي الحلقات التكرارية؟ (Loops)

هي عملية تكرار تنفيذ كتلة من اﻷوامر في البرنامج.

وهناك عدة أنواع من الحلقات التكرارية:

  • while
  • do... while
  • for

وهناك أنواعاً أخرى من الحلقات التكرارية تختلف من لغة ﻷخرى، ويختلف أسماؤها ويختلف استخدامها، لكن كل الحلقات التكرارية هي نفس المفهوم وتؤدي نفس الغرض، فأساس الحلقات التكرارية هي while ولكن اشتقت منها حلقات تكرارية أخرى تكون أسرع وأسهل في حالات معينة!

المفسر عندما يمر على الحلقة التكرارية فإنه يتحقق من الشرط، إذا كان الشرط true ينفذ اﻷوامر الموجودة بداخل الحلقة التكرارية ثم يعود مرة أخرى لبداية الحلقة التكرارية ليتحقق مرة أخرى من الشرط، فإذا كان الشرط ينتج عنه true سيقوم المفسر بتنفيذ الأوامر الموجودة بداخل الحلقة التكرارية مرة أخرى وتتكرر هذه العملية إلى أن يكون ناتج الشرط false فيتوقف المفسر عن التكرار ويمر على باقي الكود...

واﻵن لنبدأ بكتابة كود أول حلقة تكرارية...

While loop

هي النوع الرئيسي من الحلقات التكرارية، وبفهمها تكون أتقنت الحلقات التكرارية، أما باقي اﻷنواع فهي مشتقة منها لتسهّل اﻹستخدام في حالات معينة فقط.

كيفية استخدام while

هل تتذكر درس الشروط بـ if ؟ لن يختلف الوضع كثيراً هنا... تُكتب الحلقة التكرارية بهذه الطريقة:

while (/* الشرط هنا */){
  // أوامر الحلقة هنا
}

استخدمنا التعليقات comments لشرح الكود السابق... /* */ و //

في المثال السابق تتكون الحلقة من:

  • while
  • الشرط ويوضع بين اﻷقواس
  • كتلة اﻷوامر: أو نسميها (Block) وكما ذكرنا سابقاً في درس بنية الكود ، فهي توضع بين {}

هذا هو أبسط شكل للحلقة التكرارية... لنجرب طباعة اﻷعداد من 1 إلى 5:

var i = 1;
while (i <= 5){
  console.log(i);
}

ﻻ تجرب المثال السابق أبداً: فهو حلقة لا نهائية! أي إذا شغلته لن يتوقف البرنامج عن التكرار، بالتالي ربما يتوقف جهازك أو يتوقف البرنامج الذي تشغل عليه الكود! وتسمى باﻹنجليزية (Infinite Loop)

نعلم أنك ربما جربت المثال السابق وقد تعمدنا ذلك، فهو درس لن تنساه أبداً وستتجنب دائماً الوقوع في خطأ الحلقة التكرارية اللانهائية!

سنشرح المثال السابق خطوة خطوة، اﻵن كما قلنا بين اﻷقواس يوضع الشرط، وإذا كان ناتج هذا الشرط true سيقوم المفسر بتنفيذ كتلة اﻷوامر داخل الحلقة التكرارية ثم يعود للتحقق من الشرط مرة أخرى؛ فإذا تحقق الشرط وكان الناتج true سيقوم بالتكرار مرة أخرى وينفذ الكود ويعود ليتحقق وتكرر العملية هذه إلى أن ﻻ يتحقق الشرط ويكون ناتجه false

لكن في المثال السابق قلنا أن i تساوي 1 ثم وضعنا الشرط i <= 5 وبالتالي ناتج هذا الشرط true ﻷن الواحد أقل من 5! بالتالي سيقوم المفسر بتنفيذ كتلة اﻷوامر الموجودة داخل الحلقة التكرارية، أي سيطبع 1، ثم يعود المفسر يتحقق من الشرط مرة أخرى، سيجد نفس الناتج true وتظل هذه العملية في تكرار إلى مالا نهاية!!

وبالتالي المثال السابق لا يمكن أن ينجح إلا إذا تغيرت قيمة i في وقت معين لتُصبح اكبر من 5 وبالتالي ﻻ يتحقق الشرط ويتوقف المفسر عن التكرار! لذلك يمكن حل المشكلة السابقة بشيء ﻻ تخلوا منه الحلقات التكرارية (التي تتعامل مع اﻷعداد) وهو أمر تغيير القيمة! لاحظ معي المثال التالي..

var i = 1;
while (i <= 5){
  console.log(i);
  i = i + 1;
}

في المثال السابق أضفنا سطر i = i + 1 في نهاية كتلة اﻷوامر، فما فائدة هذا الأمر؟ هذا اﻷمر هو حل المشكلة التي تحدثنا عنها باﻷعلى، فبعد أن يتحقق الشرط ويدخل المفسر لتنفيذ كتلة اﻷوامر سيقوم بتنفيذ هذا اﻷمر في نهاية كتلة اﻷوامر ثم يعود ليتحقق من الشرط مرة أخرى، وهذا الأمر سيضيف 1 على قيمة i الحالية!

نطلق على المتغير i في اﻷمثلة السابقة اسم متغير العدّاد (counter) ﻷنه يُستخدم كعداد للحلقة التكرارية

مم تتكون الحلقات التكرارية العددية؟

الأمثلة السابقة هي حلقة تكرارية عددية، تتكرر عدد معين من المرات، وغالباً كل الحلقات التكرارية التي ستستخدمها ستكون عددية، فمم تتكون هذه الحلقة؟

  • :متغير العداد i هذا المتغير يُستخدم كعداد للحلقة التكرارية (counter)، وكلما تكررت الحلقة التكرارية تتغير قيمته لتصبح رقم التكرار أو الدورة الحالية، بالتالي مهمة متغير العداد مرتبطة فقط بالحلقة التكرارية وليس له أي استخدام في البرنامج خارج الحلقة التكرارية، ويمكن تسميته بأي اسم لكننا اعتادنا على تسميته i وهو اﻹسم اﻷشهر له.
  • شرط الحلقة: وبناءا عليه يتحدد هل يتم تنفيذ كتلة اﻷوامر وتكرار الحلقة أم تتوقف الحلقة.
  • كتلة اﻷوامر (block): هي مجموعة من اﻷوامر يتم تنفيذها فقط إن تحقق شرط الحلقة، ومادام شرط الحلقة يتحقق سيتم تنفيذ هذه اﻷوامر وتكرار تنفيذها إلى أن تتوقف الحلقة.
  • تغيير قيمة العداد: غالباً تكون أمر من أوامر الكتلة، وغالباً تكون في آخر كتلة اﻷوامر، وهدفها أن يتم تغيير قيمة العداد مثلاً من 1 إلى 2 ثم من 2 إلى 3 وهكذا مع كل دورة للحلقة التكرارية، وإن نسيت هذا اﻷمر ستصبح الحلقة التكرارية لا نهائية وبالتالي سيتوقف حاسوبك أو البرنامج الذي تُنفذ عليه البرنامج! ﻷن الحلقة التكرارية لن تتوقف أبداً.

كيف تعمل الحلقات التكرارية؟

فلنتخيل ما سيحدث في المثال السابق:

أولاً: سيمر المفسر على الكود ليجد الحلقة التكرارية، سيتحقق من الشرط وهو i <= 5 وقيمة i تساوي 1 إذن يكون الشرط 1 <= 5 وهذا الشرط ناتجه true


ثانياً: بما أن الشرط تحقق، سيقوم المفسر بتنفيذ اﻷوامر الموجودة بداخل الحلقة التكرارية:

  • فيقوم بطباعة i وهي قيمتها الحالية 1 بالتالي سيطبع 1
  • ثم ينفذ اﻷمر التالي i = i + 1 وهذا الأمر سيقوم بإضافة 1 على قيمة i وقيمة i في الوقت الحالي تساوي 1 إذن ستصبح i بعد هذا اﻷمر تساوي 2

ثالثاً: يعود المفسر للتحقق من الشرط مرة أخرى! ويكون الشرط في هذه المرة 2 <= 5 ﻷن i أصبحت قيمتها 2 اﻵن! وهذا الشرط ناتجه true فيقوم المفسر مرة أخرى بتنفيذ كتلة اﻷوامر:

  • فسيقوم بطباعة i وقيمتها حالياً أصبحت 2 بالتالي سيطبع 2
  • ثم ينفذ اﻷمر i = i + 1 فتصبح قيمة i الجديدة تساوي 3

ثم تتكرر نفس العملية مع 3 فيطبع المفسر 3 وتُصبح قيمة i تساوي 4، ثم يطبع المفسر 4 وتصبح قيمة i تساوي 5


رابعاً: سيعود المفسر ليتحقق من الشرط، واﻵن أصبحت قيمة i تساوي 5 فيكون الشرط هكذا 5 <= 5 وهذا الشرط يتحقق ﻷن 5 تساوي 5 بالتالي سينفذ المفسر كتلة اﻷوامر:

  • يقوم بطباعة 5
  • يقوم بإضافة 1 إلى i فتصبح قيمتها الجديدة 6

أخيراً: يعود المفسر للتحقق من الشرط مرة أخرى وقيمة i أصبحت 6 اﻵن... فيكون الشرط 6 <= 5 وهذا الشرط لا يتحقق ﻷن 6 ليست أقل من أو تساوي 5، بالتالي يكون الناتج false فيمر المفسر هذه المرة بدون تنفيذ كتلة اﻷوامر وتكون انتهت الحلقة التكرارية!

أمثلة على While

طباعة اﻷعداد من 1 إلى 10

var i = 1;
while (i <= 10){
  console.log(i);
  i = i + 1;
}

ويمكنك بنفس الطريقة طباعة اﻷعداد من 1 إلى 1000! جربها اﻵن..

جمع اﻷعداد من 1 إلى 10

جرب اﻵن جمع اﻷعداد من 1 إلى 10 (1+2+3+...+10) سيكون الناتج 55، ويمكننا كتابة حلقة تكرارية تجمع اﻷعداد من 1 إلى 10:

هذا المثال متقدم لذلك كثّف التركيز

var i = 1;
var result = 0;

while (i <= 10){
  result = result + i;
  i = i + 1;
}

console.log(result);
ناتج التشغيل 55

في المثال السابق:

  • قمنا بإنشاء متغير i قيمته 1 وهو المتغير المرتبط بالحلقة التكرارية، وقيمته 1 ﻷننا سنبدأ الحلقة من 1
  • قمنا بإنشاء متغير اسمه result وهو ناتج عملية الجمع، وفي البداية قيمته صفر ﻷننا لم نجمع عليه أي عدد حتى اﻵن (الصفر عنصر محايد للجمع)
  • قمنا بإنشاء حلقة تكرارية ستتكرر 10 مرات، من 1 إلى 10... وفي كل مرة سنقوم بإضافة i إلى result فمثلاً في البداية result قيمته 0، وi قيمته 1 إذن سنقوم بإضافة 1 إلى result فتُصبح قيمته 1، ثم تتكرر الحلقة واﻵن result = 1 و i = 2 بالتالي عند إضافة i إلى result ستكون النتيجة 3، ثم تتكرر الحلقة وتصبح قيمة reult تساوي 3 + 3 أي 6 وتتكرر هذه العملية إلى 10
  • ثم بعد إنتهاء الحلقة التكرارية وبعدما يمر المفسر لتنفيذ اﻷوامر التي تأتي بعد الحلقة التكرارية، قمنا بإضافة أمر طباعة لقيمة result حتى نعرف ما نتيجة عملية الجمع بعد التكرار 10 مرات!

ضرب اﻷعداد من 1 إلى 1000

هذه العملية شبه مستحيلة عليك بعقلك، أن تضرب اﻷعداد من 1 إلى 20 (1*2*3*4*5...*20) لكن يمكن للحاسوب القيام بها في جزء من الثانية! عن طريق الكود التالي:

var i = 1;
var result = 1;

while (i <= 20){
  result = result * i;
  i = i + 1;
}

console.log(result);
ناتج التشغيل 2432902008176640000

قم بتجربة الكود وتشغيله وانظر الناتج! يمكن استخدام محرر دليل مبرمج السريع عن طريق الضغط على الزر أسفل يسار الشاشة

تم تغيير قيمة result اﻷولية من صفر إلى 1، ﻷن في الرياضيات ضرب أي عدد * صفر = صفر، أما 1 فهو العنصر المحايد لعملية الضرب

لاحظ أننا غيرنا العملية من + إلى * وقمنا بتغيير عدد مرات التكرار من 10 إلى 20

تكرار ديناميكي

يمكن أن يكون التكرار ديناميكياً بدلاً من أن يكون ثابتاً، كيف؟ يمكن في شرط الحلقة أن نستخدم متغير كعدد تكرار بدلاً من أن يكون العدد ثابتاً فبدلاً من أن نقول مثلاً i <= 5 نقول i <= count أو أي متغير آخر، وبالتالي إن تغيرت قيمة count ستتغير عدد التكرارات في الحلقة التكرارية!

مثال يطبع اﻷعداد من صفر إلى 5:

var count = 5;
var i = 0;
while(i <= count){
  console.log(i);
  i = i + 1;
}

جرب تغيير قيمة count إلى 10 وسيطبع اﻷعداد من صفر إلى 10!

استخدام حقيقي للتكرار الديناميكي

لنفرض أننا نريد أن نطبع على الشاشة الساعات، من 1 إلى 12 ولكن نريد إضافة إعداد أو خيار إن كان مفعل تظهر الساعات من 1 إلى 24، بالتالي ستتغير عدد التكرارات ديناميكياً بناءا على هذا اﻹعداد، أي بإختصار نريد طباعة اﻷعداد من 1 إلى 12 أو من 1 إلى 24 بناءا على إعداد أو خيار، كيف يمكن تنفيذها؟

سنقوم بإنشاء متغير نوعه منطقي boolean للإعداد، فإن كانت قيمته true تظهر الساعات بنظام 24 ساعة أما إن كان false تظهر بنظام 12 ساعة بالتالي سنحتاج لاستخدام الشروط أيضاً.

var i = 1;
var hours = 12;

var hours24 = false;
if (hours24){
  hours = 24;
}

while(i <= hours){
  console.log(i);
  i = i + 1;
}

جرب اﻵن تغيير قيمة hours24 إلى true وسيقوم البرنامج بطباعة الساعات إلى 24 وليس إلى 12

hours24 هو اسم متغير اﻹعداد... إن غيرنا قيمته يتغير ناتج البرنامج من 12 ساعة إلى 24

تكرار دمج النصوص

يمكن استخدام الحلقات التكرارية في تكرار النصوص! فمثلاً نريد أن نضع قيمة لمتغير تساوي 30 نجمة * بدون أن نكتبها 30 مرة.

هذا استخدام نظري وليس استخداماً حقيقياً، ولكن في الحلقات التكرارية المتقدمة ستستخدمها في تمارين حقيقية

var result = "";

var i = 0;
while(i < 30){
  result = result + "*";
  i = i + 1;
}
console.log(result);
ناتج التشغيل ******************************

إذن في المثال السابق قيمة المتغير result أصبحت 30 نجمة!

جرب تغيير التكرار في المثال السابق إلى تكرار ديناميكي، بحيث تتغير عدد النجوم بناءا على قيمة متغير!

تمارين على الحلقات التكرارية

قم بمراجعة الدرس مرة أخرى سريعاً خصوصاً من بداية الحديث عن while حتى تتمكن من حل التمارين التالية!

تمرين

قم بكتابة كود يطبع اﻷعداد الزوجية من 0 إلى 20، أي يطبع 0، 2، 4، 6، 8... إلى 20


تمرين

استخدم الحلقات التكرارية في طباعة ناتج حساب 210 (ضرب العدد 2 في نفسه 10 مرات).


تمرين

استخدم الحلقات التكرارية في طباعة اﻷعداد من 25 إلى 1 (تنازلي)


المساهمين

وجدت خطأ أو تريد المساهمة في محتوى الدرس؟ عدل الصفحة على Github