A szerencsejátékokhoz kell valamilyen véletlenforrás. A Factor random szókészlete ad egy általános szót, a random-ot, amely alkalmazkodik ahhoz, amit átadsz neki, emellett segédszavakat a keveréshez és a mintavételhez, valamint egy módot arra, hogy a véletlent reprodukálhatóvá tedd a tesztekhez.
inline-kéntA feladat néhány részfeladatában olyan szót definiálsz, amely argumentumként egy quotationt (egy [ … ] blokkot) kap, és lefuttatja azt. A Factornak van egy szigorú szabálya erről: azt a szót, amely egy argumentumként kapott quotationt call-ol, inline-ként kell deklarálni, ezt úgy írod le, hogy közvetlenül a záró ; után odaírod az inline szót.
Az inline azt mondja a fordítónak, hogy a szó törzsét illessze be minden hívási helyre, ahelyett hogy egyszer, önmagában lefordítaná.
Íme egy kis szó, amely 10-et tesz a veremre, majd lefuttatja a kapott quotationt:
USING: kernel math prettyprint ;
: with-ten ( quot -- ) 10 swap call ; inline
A veremhatása, ( quot -- ), nem nevez meg kimenetet, mégis ha két különböző hatású quotationnel hívod meg, más-más eredményt kapsz, és mindegyik visszafolyik a hívóhoz:
[ 1 + ] with-ten . ! => 11 (quotation ( n -- n ): one value back)
[ dup 2 * ] with-ten . . ! => 20
! => 10 (quotation ( n -- n n ): two values back)
random: egy elemA random (a random szókészletben) generikus az argumentumára:
random ( obj -- elt )
n kap, egy véletlen egész számot ad vissza a [0, n) intervallumból:USING: random ;
6 random . ! 4 (a value from 0 to 5)
{ "rock" "paper" "scissors" } random . ! "paper"
Egy szabályos dobókocka dobásához eggyel eltolod a tartományt: a 6-ra hívott random 0-tól 5-ig ad értéket, így a 6 random 1 + 1-től 6-ig.
Ha rögzített számú véletlen húzást szeretnél összegyűjteni, ismételj meg egy quotationt a replicate szóval (a sequences szókészletből):
replicate ( n quot -- seq )
USING: random sequences ;
3 [ 6 random 1 + ] replicate . ! { 4 1 6 } (three dice)
randomize: helyben keverésA randomize (a random szókészletben) a sorozatot véletlen sorrendű elemekkel adja vissza:
randomize ( seq -- randomized )
{ 1 2 3 4 5 } randomize . ! { 3 1 5 2 4 }
Helyben keveri a sorozatot, és ugyanazt a sorozatot adja vissza, ezért előbb clone-ozd, ha meg akarod tartani az eredeti sorrendet.
sample: több különböző elemA sample (a random szókészletben) n különböző elemet húz egy sorozatból, akárcsak egy kártyapakli osztásakor, ahol ugyanaz a lap soha nem kerül elő kétszer:
sample ( seq n -- seq' )
{ 10 20 30 40 50 } 3 sample . ! { 40 10 30 }
Ha több elemet kérsz, mint amennyi a sorozatban van, az hiba.
Alapértelmezés szerint a random egy globális generátorból húz, amelyet a rendszeróra alapján indít el, így minden futás más. Tesztekhez, vagy amikor olyan játékot szeretnél, amelyet újra le tudsz játszani, köss egy generátort egy rögzített mag értékhez.
A <mersenne-twister> (a random.mersenne-twister szókészletben) egy egész szám magból épít generátort, a with-random (a random szókészletben) pedig lefuttat egy quotationt azzal a generátorral beállítva:
<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
A quotationön belül minden, a random, a randomize és a sample, a beállított maggal rendelkező generátorból húz, így ugyanaz a mag mindig ugyanazt az eredményt hozza.
Az a szó, amely argumentumként quotationt kap, és with-random-on keresztül futtatja, az Egy szó megjelölése inline-ként szakaszban leírt szabály alá esik: a with-random végül call-olja azt a quotationt, ezért az ilyen burkolót inline-ként kell megjelölni.
A tengerparti móló játéktermében te működteted a szerencsejátékokat. A látogatók kockát dobnak, a markolós gép nyereményt emel ki, a kártyaasztalnál pedig meg kell keverni a paklit és ki kell osztani a lapokat, mindezt a véletlen műveli. Az éjszaka végén szeretnél egy „visszajátszás” funkciót is, hogy egy vitatott játékot ugyanabból a seedből újra le lehessen játszani.
Definiáld a roll-die szót úgy, hogy átvegye az oldalak számát, és visszaadjon egy dobást az 1 és sides közötti tartományból (a határokat is beleértve).
6 roll-die .
! => 4 (some value from 1..6)
Definiáld a pick-prize szót úgy, hogy átvegyen egy nyereménysorozatot, és véletlenszerűen visszaadjon közülük egyet.
{ "teddy" "goldfish" "keyring" } pick-prize .
! => "goldfish"
Definiáld a shuffle-deck szót úgy, hogy átvegyen egy paklit (egy sorozatot), és visszaadja úgy, hogy a lapok véletlenszerű sorrendben legyenek benne.
{ 1 2 3 4 5 } shuffle-deck .
! => { 3 1 5 2 4 }
Definiáld a deal-hand szót úgy, hogy átvegyen egy paklit és egy n darabszámot, majd visszaadjon n különböző lapot a pakliból.
{ 10 20 30 40 50 } 3 deal-hand .
! => { 40 10 30 }
Definiáld a play-seeded szót úgy, hogy átvegyen egy seedet és egy idézetet, majd futtassa le az idézetet egy olyan generátorral, amelynek a seedje ebből az egész számból indul, így ugyanaz a seed mindig ugyanazt az eredményt adja. Az idézet eredményét vissza kell adni a hívónak.
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
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Factor nyelvet 47 fogalom163 feladat segítségével, valódi emberi mentorálással, mindez ingyen.