بلاك جاك

بلاك جاك

تمرين تعلّمي

مقدمة

case (يُشار إليه غالبًا بـ switch في لغات أخرى) هو أحد أشكال تعبيرات التحكم مثل if-else. يتيح case ربط عدة عبارات if-else-if معًا، وقد يكون أكثر قابلية للقراءة، ويتيح تراكيب قوية.

يُعرَّف case بالكلمة المفتاحية case متبوعة بتعبير اختياري. ثم تُستخدم الكلمة المفتاحية when لكل حالة، متبوعة بتعبير يُقارَن بتعبير case. وينبغي ألا تُزاح الكلمة المفتاحية when عن الكلمة المفتاحية case. ويأتي بعد الكلمة المفتاحية when الكود الذي ينبغي تنفيذه إذا طابق تعبير case تعبير when. ويتيح case عبارة else اختيارية تُنفَّذ إذا لم تتطابق أي حالة أخرى.

يُقيَّم تعبير case ثم يُقارَن بكل تعبير when. وتتم المقارنة باستخدام عامل الاندراج في case (===).

case 1
when 1
  puts "One"
when 2
  puts "Two"
else
  puts "Other"
end
# => One

# This is the same as:
tmp = 1
if 1 === tmp
  puts "One"
elsif 2 === tmp
  puts "Two"
else
  puts "Other"
end

عامل الاندراج في case (===)

يختلف عامل الاندراج في case (===) قليلًا عن عامل المساواة (==). يتحقق العامل مما إذا كان الطرف الأيمن عضوًا في المجموعة التي يصفها الطرف الأيسر. وهذا يعني أن موضع كل طرف مهم. وتعتمد طريقة عمله على نوع الطرف الأيسر؛ فمثلًا يتحقق Range مما إذا كان الطرف الأيمن داخل المدى، بينما يتحقق Object مما إذا كان الطرف الأيمن نسخة من Object.

(1..3) == 1  # => false
(1..3) === 1 # => true

String == "foo"  # => false
String === "foo" # => true

الحالات مع عدة تعبيرات

تتيح الحالات مطابقة عدة تعبيرات في حالة واحدة، مع فصل كل قيمة ممكنة بفاصلة. وسيُنفَّذ الكود إذا طابق أي من التعبيرات. وقد يكون هذا مفيدًا لحالة واحدة لها عدة قيم ممكنة.

case 1
when 1, 2
  puts "One or two"
else
  puts "Other"
end

الحالات مع المديات

يمكن للحالات أيضًا التحقق مما إذا كانت قيمة ما داخل مدى. ويتم ذلك بوضع مدى كتعبير when.

case var
when 1..3
  puts "One to three"
else
  puts "Other"
end

الحالات بدون تعبير case

عندما لا تكون هناك حاجة إلى تعبير case، يمكن حذفه. وسيؤدي ذلك إلى تقييم كل تعبير when من حيث كونه صحيحًا أو خطأً. فتبدو هذه الحالات وكأنها تتصرف مثل عبارات if-else-if.

case
when 1 == 1
  puts "One is equal to one"
when 1 > 2
  puts "One is greater than two"
else
  puts "Other"
end

when في سطر واحد

يتيح Crystal عبارات case في سطر واحد. ويمكن استخدام ذلك عندما تكون لديك عبارة بسيطة من سطر واحد. وتُكتب عبارة when في السطر الواحد بالشكل when <expression> then <statement>. وعند استخدامها في عبارة else، تُكتب بالشكل else <statement>.

case var
when 1 then puts "One"
when 2 then puts "Two"
else puts "Other"
end

الحالات مع الأنواع

يتيح case المطابقة مع الأنواع. وستستخدم المقارنة عامل is_a? للتحقق من نوع المتغير. فمثلًا، يتيح ذلك فرعًا لكل نوع في نوع اتحادي.

case var
when Int32
  puts "Int32"
when String
  puts "String"
else
  puts "Other"
end

الكائن الضمني

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

case 1
when .odd?
  puts "Odd"
when .even?
  puts "Even"
end

التعليمات

في هذا التمرين سنحاكي الجولة الأولى من لعبة Blackjack.

1. احسب قيمة أي ورقة معطاة.

ستتلقى ورقتين وستتمكن من رؤية الورقة المكشوفة للموزّع. تُمثَّل جميع الأوراق بسلسلة نصية مثل "ace" و"king" و"three" و"two" وغيرها. قيم كل ورقة هي:

الورقة القيمة الورقة القيمة
ace 11 eight 8
two 2 nine 9
three 3 ten 10
four 4 jack 10
five 5 queen 10
six 6 king 10
seven 7 other 0
Note

عادةً، يمكن أن تأخذ أوراق الآس القيمة 1 أو 11، لكن للتبسيط سنفترض أنها تأخذ القيمة 11 فقط.

نفّذ الطريقة Blackjack.parse_card التي تأخذ ورقة كسلسلة نصية كوسيط. يجب أن تُرجع الطريقة قيمة الورقة كعدد صحيح.

Blackjack.parse_card("ace")
# => 11

2. سمِّ نطاقات القيم.

يجب تصنيف نقاط اللاعب إلى نطاقات من القيم. تُحسب نقاط اللاعب بجمع قيم ورقتَي اللاعب. النطاقات المستخدمة هي:

النطاق القيمة
low [4, 11]
mid [12, 16]
high [17, 20]
blackjack [21]

نفّذ الطريقة Blackjack.card_range التي تأخذ ورقتين كسلسلتين نصيتين كوسيطين. يجب أن تُرجع الطريقة اسم نطاق القيم الذي تقع فيه الورقتان.

Blackjack.card_range("ten", "king")
# => "high"

3. نفّذ منطق القرار للجولة الأولى.

بناءً على ورقتيك وورقة الموزّع، توجد استراتيجية للجولة الأولى من اللعبة، وفيها الخيارات التالية:

  • الوقوف (S)
  • السحب (H)
  • التقسيم (P)
  • الفوز التلقائي (W)

رغم أنها ليست مثالية بعد، ستتبع الاستراتيجية التي كان صديقك Alex يطوّرها، وهي كما يلي:

  • إذا كان لديك زوج من أوراق الآس فيجب دائمًا تقسيمه.
  • إذا كان لديك Blackjack (ورقتان مجموعهما 21)، ولم يكن لدى الموزّع ورقة آس أو ورقة صورية أو عشرة، فأنت تفوز تلقائيًا. أما إذا كان لدى الموزّع أي من هذه الأوراق، فعليك أن تقف وتنتظر كشف الورقة الأخرى.
  • إذا كان مجموع ورقتيك ضمن النطاق [17, 20] فيجب أن تقف دائمًا.
  • إذا كان مجموع ورقتيك ضمن النطاق [12, 16] فيجب أن تقف دائمًا إلا إذا كان لدى الموزّع 7 أو أعلى، وفي هذه الحالة يجب أن تسحب دائمًا.
  • إذا كان مجموع ورقتيك 11 أو أقل فيجب أن تسحب دائمًا.

نفّذ الطريقة Blackjack.first_turn التي تأخذ ثلاث أوراق كسلاسل نصية كوسائط. يجب أن تُرجع الطريقة القرار الذي ينبغي أن تتخذه كسلسلة نصية.

Blackjack.first_turn("ace", "ace", "two")
# => "P"
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Crystal Exercism

مستعد لبدء بلاك جاك؟

سجّل في Exercism لتتعلّم وتتقن Crystal عبر 26 مفهومًا142 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.