تحتاج ألعاب الحظّ إلى مصدر للعشوائية. توفّر مفردات random في Factor كلمة عامّة واحدة، هي random، تتكيّف مع أي شيء تمرّره إليها، إضافة إلى أدوات مساعدة للخلط وأخذ العيّنات، وطريقة تجعل العشوائية قابلة لإعادة الإنتاج في الاختبارات.
inline
تُعرّف بعض مهام هذا التمرين كلمة تأخذ اقتباسًا (كتلة [ … ]) كوسيط وتشغّله. ولدى Factor قاعدة صارمة واحدة بهذا الشأن: الكلمة التي تستدعي بـ call اقتباسًا وصل إليها كوسيط لا بد أن تُعرَّف بأنها inline، ويُكتب ذلك بوضع inline بعد ; الختامية مباشرة.
يخبر inline المترجمَ أن يدمج جسم الكلمة في كل موضع استدعاء بدلًا من ترجمته مرة واحدة بمفرده.
إليك كلمة صغيرة تدفع 10 إلى المكدّس ثم تشغّل الاقتباس الذي وُصل إليها:
USING: kernel math prettyprint ;
: with-ten ( quot -- ) 10 swap call ; inline
أثر المكدّس الخاص بها، ( quot -- )، لا يسمّي أي مخرجات، ومع ذلك فإن استدعاءها باقتباسين لهما أثران مختلفان ينتج نتائج مختلفة، تعود كلها إلى المستدعي:
[ 1 + ] with-ten . ! => 11 (quotation ( n -- n ): one value back)
[ dup 2 * ] with-ten . . ! => 20
! => 10 (quotation ( n -- n n ): two values back)
random: عنصر واحدrandom (في random) عامّة بالنسبة إلى وسيطها:
random ( obj -- elt )
n، تُرجع عددًا صحيحًا عشوائيًا في المجال [0, n):USING: random ;
6 random . ! 4 (a value from 0 to 5)
{ "rock" "paper" "scissors" } random . ! "paper"
لرمي حجر نرد عادي تُزحزح المجال بمقدار واحد: random للعدد 6 تعطي من 0 إلى 5، لذا يعطي 6 random 1 + من 1 إلى 6.
لجمع عدد ثابت من السحبات العشوائية، كرّر اقتباسًا باستخدام replicate (في sequences):
replicate ( n quot -- seq )
USING: random sequences ;
3 [ 6 random 1 + ] replicate . ! { 4 1 6 } (three dice)
randomize: الخلط في المكانتُرجع randomize (في random) التسلسل وقد صارت عناصره بترتيب عشوائي:
randomize ( seq -- randomized )
{ 1 2 3 4 5 } randomize . ! { 3 1 5 2 4 }
إنها تخلط في المكان وتُرجع التسلسل نفسه، لذا استخدم clone أولًا إذا احتجت إلى الحفاظ على الترتيب الأصلي.
sample: عدة عناصر متمايزةتسحب sample (في random) عددًا n من العناصر المتمايزة من تسلسل، مثل توزيع يد من أوراق اللعب، فلا تتكرر الورقة نفسها مرتين:
sample ( seq n -- seq' )
{ 10 20 30 40 50 } 3 sample . ! { 40 10 30 }
طلب عناصر أكثر مما يحتويه التسلسل يُعدّ خطأً.
افتراضيًا، تسحب random من مولّد عامّ مبذور من ساعة النظام، لذا تختلف كل عملية تشغيل. في الاختبارات، أو في أي وقت تريد فيه لعبة يمكنك إعادة تشغيلها، اربط مولّدًا بـبذرة ثابتة.
تبني <mersenne-twister> (في random.mersenne-twister) مولّدًا من بذرة عددية صحيحة، وتشغّل with-random (في random) اقتباسًا وقد ثُبّت ذلك المولّد:
<mersenne-twister> ( seed -- rnd )
with-random ( rnd quot -- )
USING: random random.mersenne-twister ;
42 <mersenne-twister> [ 6 random 1 + ] with-random .
! always the same value for seed 42
كل ما داخل الاقتباس (random وrandomize وsample) يسحب من المولّد المبذور، لذا تعيد البذرة نفسها دائمًا النتيجة نفسها.
الكلمة التي تأخذ اقتباسًا كوسيط وتشغّله عبر with-random تخضع للقاعدة الواردة في تعليم كلمة بأنها inline: ينتهي with-random إلى استدعاء ذلك الاقتباس بـ call، لذا يجب تعليم غلاف كهذا بأنه inline.
أنت تدير ألعاب الحظ في صالة الألعاب على ممشى الشاطئ. يرمي اللاعبون النرد، وتلتقط آلة المخالب جائزة، وتحتاج طاولة البطاقات إلى خلط رزمتها وتوزيع الأيدي. كل ذلك يعمل بالعشوائية. وفي نهاية الليلة تريد أيضًا ميزة "إعادة التشغيل" حتى يمكن تشغيل لعبة متنازع عليها مرة أخرى من البذرة نفسها.
عرّف roll-die بحيث تأخذ عدد الأوجه وتُرجع رمية في النطاق من 1 إلى sides (شاملًا الطرفين).
6 roll-die .
! => 4 (some value from 1..6)
عرّف pick-prize بحيث تأخذ متتالية من الجوائز وتُرجع واحدة منها عشوائيًا.
{ "teddy" "goldfish" "keyring" } pick-prize .
! => "goldfish"
عرّف shuffle-deck بحيث تأخذ رزمة (متتالية) وتُرجعها وقد رُتّبت بطاقاتها بترتيب عشوائي.
{ 1 2 3 4 5 } shuffle-deck .
! => { 3 1 5 2 4 }
عرّف deal-hand بحيث تأخذ رزمة وعددًا n، وتُرجع n من البطاقات المختلفة من الرزمة.
{ 10 20 30 40 50 } 3 deal-hand .
! => { 40 10 30 }
عرّف play-seeded بحيث تأخذ بذرة وquotation، وتشغّل quotation باستخدام مولّد بذرته ذلك العدد الصحيح، بحيث تُنتج البذرة نفسها دائمًا النتيجة نفسها. وينبغي إرجاع نتيجة quotation إلى المستدعي.
42 [ 6 roll-die ] play-seeded .
! => the same value every time for seed 42
! Same seed, same game:
99 [ 5 deal-hand ] play-seeded 99 [ 5 deal-hand ] play-seeded = .
! => t
سجّل في Exercism لتتعلّم وتتقن Factor عبر 47 مفهومًا163 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.