الجمل الشرطية في Kotlin - الجزء 1

في هذا الدرس العملي حول الترميز بلغة Kotlin، ستنشئ لعبة أخرى باستخدام النرد، وهي Lucky Dice Roll، وستحاول الحصول على رقم الحظ. سيحدّد البرنامج رقمًا محظوظًا ثم سيرمي النرد. بعد ذلك، يمكنك مقارنة الرمية بالرقم المحظوظ وطباعة رسالة مناسبة في الناتج. ولتحقيق ذلك، ستتعرّف على كيفية مقارنة القيم واتّخاذ قرارات مختلفة في برنامج Kotlin.

لمساعدتك في التركيز على مفاهيم البرمجة بدون الحاجة إلى القلق بشأن واجهة مستخدم التطبيق، ستستخدم أداة برمجة Kotlin المستندة إلى المتصفّح وستعرض نتائجك في وحدة التحكّم.

المتطلبات الأساسية

  • كيفية فتح الرمز البرمجي وتعديله وتشغيله في https://try.kotlinlang.org/
  • القدرة على إنشاء برنامج Kotlin وتشغيله يستخدم متغيرات ودوال مع وسيطات وفئات مع طرق، ويعرض نتيجة في وحدة التحكّم

أهداف الدورة التعليمية

  • كيفية استخدام عبارتَي if وelse
  • كيفية مقارنة القيم باستخدام عوامل مثل أكبر من (>) وأصغر من (<) ويساوي (==)
  • كيفية استخدام عبارات when لاختيار أحد الخيارات استنادًا إلى قيمة معيّنة
  • ما هو نوع البيانات Boolean وكيفية استخدام القيمتين true وfalse لاتخاذ القرارات

ما ستنشئه

  • لعبة النرد المستندة إلى Kotlin، Lucky Dice Roll، والتي تتيح لك تحديد رقم الحظ. يفوز اللاعب إذا حصل على الرقم المحظوظ.

ما تحتاج إليه

  • جهاز كمبيوتر متصل بالإنترنت

يجب أن يحدّد برنامج Lucky Dice Roller ما إذا كان المستخدم قد حصل على رقم الحظ وتلقّى رسالة تهنئة، أو تلقّى رسالة تطلب منه إعادة المحاولة.

بصفتك مطوّر تطبيقات، عليك اتّخاذ قرارات بشأن طريقة عمل التطبيق وإنشاء نتائج مختلفة للمستخدمين.

إذا كنت بصدد إنشاء تطبيق تسوّق، يمكنك عرض شاشات مختلفة استنادًا إلى خيارات التسليم التي يختارها المستخدم. في لعبة اختبار، يمكنك عرض شاشات مختلفة استنادًا إلى ما إذا كانت إجابة اللاعب صحيحة. اعتمادًا على التطبيق، قد تكون هناك العديد من النتائج المحتملة التي يجب أخذها في الاعتبار في التعليمات البرمجية.

في برنامج "رمي النرد"، يجب أن يتعامل التطبيق مع حالات مختلفة، مثل:

  • إذا كان رمي النرد هو الرقم المحظوظ، اعرض رسالة تهنئة.
  • في حال لم يكن رمي النرد هو الرقم المحظوظ، اعرض رسالة لإعادة المحاولة.

لإضافة هذه المنطق إلى الرمز البرمجي، استخدِم كلمات رئيسية خاصة بلغة Kotlin، مثل if وelse وwhen.

لنلقِ نظرة على بعض الأمثلة.

استخدِم عبارة if لإعداد شرط يتم استيفاؤه

  1. راجِع الرمز البرمجي أدناه. هل يمكنك تخمين الناتج؟
fun main() {
   val num = 5
   if (num > 4) {
       println("The variable is greater than 4")
   }
}
  1. انسخ الرمز والصقه في محرّر برنامج Kotlin وشغِّل البرنامج لمراقبة الناتج.
The variable is greater than 4

تتم عملية اتخاذ القرار في هذا البرنامج على النحو التالي:

  1. أنشئ متغيّرًا num واضبطه على 5.
  2. إذا كان num أكبر (>) من 4,، اطبع "The variable is greater than 4".
  3. في جميع الحالات الأخرى، لا تتّخذ أي إجراء.

في المثال أعلاه، تم ضبط num على 5. تقارن عبارة if ما إذا كان المتغيّر أكبر من 4. بما أنّ هذا الشرط صحيح، سينفّذ النظام بعد ذلك التعليمات الواردة بين الأقواس المتعرّجة ويطبع الرسالة.

لاحظ التنسيق العام لعبارة if:

  • ابدأ بالكلمة الرئيسية if.
  • أضِف قوسَين (). يتم وضع الشرط داخل الأقواس. الشرط هو أي شيء يمكن أن يكون true أو false. على سبيل المثال، ما إذا كان رقم أكبر من رقم آخر.
  • أضِف بعد ذلك علامتَي قوسَين معقوفَين {}. داخل الأقواس المعقوفة، يمكنك وضع الرمز المراد تنفيذه إذا كان الشرط true.
if (condition-is-true) {
    execute-this-code
}

استخدِم عبارة if لإعداد شرط لم يتم استيفاؤه

  1. غيِّر قيمة num إلى 3، كما هو موضّح أدناه. ماذا تتوقّع أن يحدث إذا شغّلت هذه الرمز؟
fun main() {
   val num = 3
   if (num > 4) {
       println("The variable is greater than 4")
   }
}
  1. انسخ الرمز والصقه في محرّر برنامج Kotlin وشغِّل البرنامج لمراقبة الناتج.

عند ضبط num على 3، لا تتم طباعة أي شيء لأنّ قيمة num أقل من 4. إذًا، الشرط الذي ينص على أنّ num أكبر من 4 هو false، ولن يتم تنفيذ الرمز بين الأقواس المتعرّجة، ولن تتم طباعة أي شيء.

استخدِم else لإنشاء بديل للشروط التي لم يتم استيفاؤها

بدلاً من عدم اتّخاذ أي إجراء، يمكنك أن تقدّم للمستخدمين بديلاً عندما لا يتم استيفاء أحد الشروط. كما هو الحال مع اللغة العادية، يمكنك إجراء ذلك باستخدام عبارة else.

  1. أضِف عبارة else لطباعة رسالة عندما لا تكون قيمة num أكبر من 4، كما هو موضّح أدناه. ماذا تتوقّع أن يحدث إذا شغّلت هذه الرمز؟
fun main() {
   val num = 3
   if (num > 4) {
       println("The variable is greater than 4")
   } else {
       println("The variable is less than 4")
   }
}
  1. انسخ الرمز والصقه في محرّر برنامج Kotlin وشغِّل البرنامج لمراقبة الناتج.
The variable is less than 4
  1. لاحظ أنّه عندما تكون قيمة num هي 3، يعرض البرنامج الرسالة "The variable is less than 4" المرتبطة بالعبارة else لأنّ num ليست أكبر من 4 .
  2. غيِّر قيمة num إلى 5 وشغِّل البرنامج مرة أخرى. الآن، من الصحيح أنّ num أكبر من 4، وسيطبع البرنامج "The variable is greater than 4".
  3. غيِّر قيمة num إلى 4 وشغِّل البرنامج. الآن، 4 ليس أكبر من 4، ويطبع البرنامج "The variable is less than 4".

على الرغم من أنّ "The variable is less than 4" هو الناتج الصحيح للشروط التي حدّدتها في الرمز، فإنّ العبارة المطبوعة ليست دقيقة، لأنّ 4 ليس أقل من 4. يمكنك إضافة شرط آخر يتحقّق من الاحتمال الثالث، أي ما إذا كانت قيمة num تساوي 4 بالضبط، وطباعة عبارة صحيحة عندما يكون هذا الشرط صحيحًا.

استخدِم تركيبة else + if لإضافة شروط بديلة

يمكنك إضافة أكثر من شرط واحد. بالنسبة إلى المثال الذي قدّمته، إليك كيفية تغطية جميع الاحتمالات الخاصة بـ num:

  • إذا كان num أكبر من 4، اطبع "The variable is greater than 4".
  • إذا كان num يساوي 4، اطبع "The variable is equal to 4".
  • بخلاف ذلك، اطبع "The variable is less than 4".

ويُشار إلى هذه الحالات باسم حالات مختلفة في عبارة if-else. هناك 3 طلبات مُدرَجة.

يبدو الرمز المعدَّل على النحو التالي:

fun main() {
   val num = 4
   if (num > 4) {
       println("The variable is greater than 4")
   } else if (num == 4) {
       println("The variable is equal to 4")
   } else {
       println("The variable is less than 4")
   }
}

لاحظ التغييرات التالية:

  • تم الآن ضبط قيمة num على 4 حتى تتمكّن من اختبار الشرط الجديد.
  • بين عبارتَي if وelse الأصليتَين، توجد عبارة else if جديدة للحالة التي تكون فيها قيمة num تساوي 4 بالضبط.
  1. انسخ الرمز أعلاه والصقه في محرّر برنامج Kotlin وشغِّل البرنامج لمراقبة الناتج.
The variable is equal to 4
  1. جرِّب تغيير قيمة num، واطّلِع على تأثير ذلك في الناتج. غيِّر num إلى 2 و6، حتى تتمكّن من رؤية كل شرط true.

التحكّم في التدفق

عند النظر إلى عبارات if-else أعلاه، سيتم تنفيذ الرمز أو تدفقه، كما هو محدّد بالشروط. لذا، تُعرف الطريقة التي توجّه بها التنفيذ باستخدام هذه العبارات الشرطية باسم "تدفّق التحكّم" في البرنامج.

  • لنفترض أنّ نتيجة رمية النرد num هي 3. يتحقّق البرنامج من الشرط الأول (num > 4). هذا الشرط غير صحيح، لذا يتحقّق البرنامج من الشرط التالي (num == 4) الذي يكون أيضًا غير صحيح. بعد ذلك، ينفّذ البرنامج الرمز البرمجي لعبارة else، وهو الخيار الأخير.
  • إذا كان رقم رمية النرد هو 6، يكون الشرط الأول (num > 4) صحيحًا. يطبع البرنامج الرسالة "The variable is greater than 4". بما أنّ هذا الشرط صحيح، ليس عليه التحقّق من الباقي، وينتهي من عبارة if-else.
  • استخدِم تركيبة else + if لإضافة شروط بديلة.

في هذا القسم، وباستخدام ما تعلّمته في المهمة السابقة، ستعدّل برنامج "رمي النرد" للتحقّق مما إذا كنت قد حصلت على رقم حظ محدّد مسبقًا. إذا كان لديك، فقد فزت!

إعداد الرمز الأوّلي

ستبدأ لعبة Lucky Dice Roller باستخدام رمز مشابه لرمز الحلّ في برنامج Dice Roller السابق بلغة Kotlin. يمكنك تعديل الدالة main() في الرمز السابق لتتطابق مع الرمز أدناه، أو يمكنك نسخ الرمز أدناه ولصقه للبدء.

fun main() {
    val myFirstDice = Dice(6)
    val diceRoll = myFirstDice.roll()
    println("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")
}

class Dice (val numSides: Int) {

    fun roll(): Int {
        return (1..numSides).random()
    }
}

التحقّق مما إذا تم طرح الرقم المحظوظ

أنشئ رقم حظ أولاً، ثم قارِن رمية النرد بهذا الرقم.

.

  1. في main()، احذف عبارة println().
  2. في main()، أضِف val باسم luckyNumber واضبط قيمته على 4. يجب أن تبدو التعليمات البرمجية على النحو التالي.
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
}
  1. في ما يلي، أضِف عبارة if مع شرط داخل الأقواس () يتحقّق مما إذا كان rollResult يساوي (==) luckyNumber. اترك بعض المساحة بين الأقواس المتعرّجة {} لتتمكّن من إضافة المزيد من الرموز.
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
    if (rollResult == luckyNumber) {

    }
}
  1. داخل الأقواس المتعرّجة {}، أضِف عبارة println لطباعة "You win!"
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    }
}
  1. تشغيل برنامجك قد تحتاج إلى تشغيله عدة مرات قبل أن يحالفك الحظ وتظهر الرسالة الفائزة في الناتج.
You win!

الردّ عندما لم يتم طرح الرقم المحظوظ

قد يؤدي عدم تلقّي أي ملاحظات من البرنامج في حال عدم فوز المستخدم إلى التساؤل عمّا إذا كان البرنامج معطّلاً. من الممارسات الجيدة تقديم ردّ دائمًا عندما ينفّذ المستخدم إجراءً ما. بالنسبة إلى برنامج Lucky Dice Roller، يمكنك إعلامهم بأنّهم لم يفوزوا باستخدام عبارة else.

  1. أضِف عبارة else لطباعة "You didn't win, try again!".
fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4

   if (rollResult == luckyNumber) {
       println("You win!")
   } else {
       println("You didn't win, try again!")
   }
}
  1. نفِّذ البرنامج، وسيتم إعلام المستخدمين دائمًا بالنتيجة بغض النظر عن طبيعتها.

في هذه المرحلة، يعرف المستخدمون ما إذا كانوا قد فازوا أم لا، ولكنهم لا يعرفون السبب. احرص دائمًا على تزويد المستخدمين بمعلومات ليفهموا نتيجة إجراءاتهم. لنفترض أنّ برنامجك كان عبارة عن طلب للحصول على قرض. "لم تتم الموافقة على طلبك لأنّ تقييمك الائتماني ضعيف"، هذه الجملة تقدّم معلومات أكثر بكثير من "عذرًا، لا يمكننا منحك قرضًا، يُرجى إعادة المحاولة". بالنسبة إلى لعبة Lucky Dice Roller، يمكنك عرض رسالة إعلامية مختلفة للمستخدمين في كل رمية إذا خسروا. استخدِم عبارات else if متعددة لإجراء ذلك.

  1. أضِف عبارات else if لطباعة رسالة مختلفة لكل عملية دحرجة. راجِع التنسيق الذي تعلّمته في المهمة السابقة، إذا لزم الأمر.
fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4

   if (rollResult == luckyNumber) {
       println("You win!")
   } else if (rollResult == 1) {
       println("So sorry! You rolled a 1. Try again!")
   } else if (rollResult == 2) {
       println("Sadly, you rolled a 2. Try again!")
   } else if (rollResult == 3) {
       println("Unfortunately, you rolled a 3. Try again!")
   } else if (rollResult == 4) {
       println("No luck! You rolled a 4. Try again!")
   } else if (rollResult == 5) {
       println("Don't cry! You rolled a 5. Try again!")
   } else {
       println("Apologies! you rolled a 6. Try again!")
   }
}

في الرمز أعلاه، يمكنك

  • تحقَّق مما إذا كانت rollResult هي luckyNumber.
  • إذا كان rollResult هو luckyNumber، اطبع رسالة الفوز.
  • في ما عدا ذلك، تحقَّق مما إذا كانت قيمة rollResult هي 1، وإذا كان الأمر كذلك، اطبع رسالة "أعِد المحاولة".
  • بخلاف ذلك، تحقَّق مما إذا كانت قيمة rollResult هي 2، وإذا كان الأمر كذلك، اطبع رسالة مختلفة لإعادة المحاولة.
  • وبخلاف ذلك، استمر في التحقّق من خلال الرقم 5.
  • إذا لم يكن الرقم أيًا من 1 إلى 5، يكون الخيار المتبقي هو 6 فقط، لذا لا حاجة إلى اختبار آخر باستخدام else if، ويمكنك فقط الحصول على هذا الخيار الأخير باستخدام عبارة else النهائية.

بما أنّ وجود عدة حالات else if أمر شائع جدًا، توفّر Kotlin طريقة أبسط لكتابتها.

يُعدّ اختبار العديد من النتائج أو الحالات المختلفة أمرًا شائعًا جدًا في البرمجة. في بعض الأحيان، يمكن أن تكون قائمة النتائج المحتملة طويلة جدًا. على سبيل المثال، إذا كنت تستخدم نردًا ذا 12 وجهًا، سيكون لديك 11 عبارة else if بين النجاح وelse النهائي. لتسهيل كتابة وقراءة هذه الأنواع من العبارات، ما يساعد في تجنُّب الأخطاء، تتيح لغة Kotlin عبارة when.

ستغيّر برنامجك لاستخدام عبارة when. تبدأ عبارة when بالكلمة الأساسية when، متبوعة بأقواس (). داخل الأقواس، يتم وضع القيمة المطلوب اختبارها. يلي ذلك أقواس معقوفة {} للتعليمات البرمجية التي سيتم تنفيذها في حال توفّر شروط مختلفة.

  1. في برنامجك، في main()، اختَر الرمز من عبارة if الأولى إلى القوس المعقوف } الذي يغلق عبارة else الأخيرة واحذفه.
fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4
}
  1. في main()، أسفل تعريف luckyNumber، أنشئ عبارة when. بما أنّ when يجب أن يتم اختباره مقابل النتيجة التي تم طرحها، ضَع rollResult بين الأقواس (). أضِف أقواسًا معقوفة {} مع بعض المسافات الإضافية، كما هو موضّح أدناه.
fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4

   when (rollResult) {

   }
}

كما كان من قبل، اختبِر أولاً ما إذا كان rollResult هو نفسه luckyNumber.

  1. داخل الأقواس المتعرّجة {} لعبارة when، أضِف عبارة تختبر rollResult مقابل luckyNumber، وإذا كانا متطابقَين، اطبع الرسالة الفائزة. يبدو البيان على النحو التالي:
luckyNumber -> println("You win!")

وهذا يعني ما يلي:

  • عليك أولاً وضع القيمة التي تريد مقارنتها بـ rollResult. هذا هو luckyNumber.
  • أضِف بعد ذلك سهمًا (->).
  • بعد ذلك، أضِف الإجراء الذي سيتم تنفيذه في حال العثور على تطابق.

يمكن قراءة ذلك على النحو التالي: "إذا كان rollResult هو luckyNumber، اطبع الرسالة "You win!"".

وسيبدو رمز main() على النحو التالي.

fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4

   when (rollResult) {
       luckyNumber -> println("You win!")
   }
}
  1. استخدِم النمط نفسه لإضافة أسطر ورسائل للأرقام المحتملة من 1 إلى 6، كما هو موضّح أدناه. يجب أن تبدو دالة main() المكتملة على النحو التالي.
fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4

   when (rollResult) {
       luckyNumber -> println("You won!")
       1 -> println("So sorry! You rolled a 1. Try again!")
       2 -> println("Sadly, you rolled a 2. Try again!")
       3 -> println("Unfortunately, you rolled a 3. Try again!")
       4 -> println("No luck! You rolled a 4. Try again!")
       5 -> println("Don't cry! You rolled a 5. Try again!")
       6 -> println("Apologies! you rolled a 6. Try again!")
   }
}
  1. تشغيل برنامجك لا يوجد فرق في الناتج، ولكن التعليمات البرمجية تكون أكثر إيجازًا وأسهل في القراءة.

تهانينا! لقد تعلّمت طريقتَين لطباعة الرسائل استنادًا إلى شرط معيّن. هذه أداة فعّالة لكتابة برامج مثيرة للاهتمام.

fun main() {
   val myFirstDice = Dice(6)
   val rollResult = myFirstDice.roll()
   val luckyNumber = 4

   when (rollResult) {
       luckyNumber -> println("You won!")
       1 -> println("So sorry! You rolled a 1. Try again!")
       2 -> println("Sadly, you rolled a 2. Try again!")
       3 -> println("Unfortunately, you rolled a 3. Try again!")
       4 -> println("No luck! You rolled a 4. Try again!")
       5 -> println("Don't cry! You rolled a 5. Try again!")
       6 -> println("Apologies! you rolled a 6. Try again!")
   }
}

class Dice(val numSides: Int) {
   fun roll(): Int {
       return (1..numSides).random()
   }
}
  • استخدِم عبارة if لضبط شرط لتنفيذ بعض التعليمات. على سبيل المثال، إذا حصل المستخدم على الرقم المحظوظ، اطبع رسالة فوز.
  • يحتوي نوع البيانات Boolean على القيمتين true وfalse ويمكن استخدامه لاتخاذ القرارات.
  • مقارنة القيم باستخدام عوامل التشغيل، مثل أكبر من (>) وأصغر من (<) ويساوي (==)
  • استخدِم سلسلة من عبارات else if لضبط شروط متعدّدة. على سبيل المثال، اطبع رسالة مختلفة لكل رمية نرد محتملة.
  • استخدِم عبارة else في نهاية سلسلة من الشروط لرصد أي حالات قد لا يتمّ تغطيتها بشكل صريح. إذا كنت تغطي حالات النرد ذي 6 أوجه، ستلتقط عبارة else الرقمَين 7 و8 اللذين تم رميهما بنرد ذي 8 أوجه.
  • استخدِم عبارة when كشكل مضغوط لتنفيذ الرمز البرمجي استنادًا إلى مقارنة قيمة.

يُرجى اتّباع الخطوات التالية:

  1. غيِّر myFirstDice ليتضمّن 8 أضلاع وشغِّل الرمز. الإجراء

ملاحظة: عند زيادة عدد الأضلاع، لن تغطّي عبارة when جميع الحالات بعد الآن، لذا لن تتم طباعة أي شيء للحالات غير المغطّاة.

  1. أصلِح عبارة when لتشمل جميع الجوانب الثمانية. يمكنك إجراء ذلك عن طريق إضافة حالات للأرقام الإضافية. التحدي: بدلاً من إضافة حالة جديدة لكل رقم، استخدِم عبارة else لتغطية جميع الحالات التي لم يتم تناولها بشكل صريح.

ملاحظة: يمكنك إضافة المزيد من الحالات لتغطية المزيد من الجوانب. هذه طريقة جيدة لإجراء ذلك، إذا كنت تريد رسالة مختلفة لكل رقم يمكن طرحه. أو يمكنك استخدام عبارة else وطباعة الرسالة نفسها لجميع الجوانب الأكبر من 6 التي يغطيها الرمز الحالي.

  1. غيِّر عدد أوجه النرد إلى 4 فقط.myFirstDice الإجراء

ملاحظة: لن يكون لتغيير عدد أوجه النرد إلى أقل من العدد الذي تغطيه عبارة when أي تأثير ملحوظ، لأنّ جميع الحالات التي يمكن أن تحدث مشمولة.