Kurzusok
/
Factor
Factor
/
Feladatok
/
Mólójátékok
Mólójátékok

Mólójátékok

Tanulófeladat

Bevezetés

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.

Egy szó megjelölése inline-ként

A 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á.

  • A hívó quotationje közvetlenül beillesztődik, így bármit hagy a quotation a vermen, az visszafolyik a hívóhoz, pedig a szó saját veremhatása nem deklarál kimenetet.

Í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 elem

A random (a random szókészletben) generikus az argumentumára:

random ( obj -- elt )
  • Ha egy egész számot 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)
  • Ha egy sorozatot kap, egy véletlen elemet ad vissza:
{ "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.

Több érték kihúzása

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és

A 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ő elem

A 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.

Reprodukálható véletlen

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.

Utasítások

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.

1. Dobj egy kockával

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)

2. Szerezz nyereményt

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"

3. Keverd meg a paklit

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 }

4. Oszd ki a lapokat

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 }

5. Visszajátszás seedből

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
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Factor Exercism

Készen állsz elkezdeni a(z) Mólójátékok feladatot?

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.