2016-05-14 5 views
13

Ich bin neu in Elm und wurde in dem folgende Beispiel suche (beachten Sie diese unter der neueren 0,17 Architektur ist, wo Aktion jetzt ist Command): http://elm-lang.org/examples/randomWie füge ich diesem Beispiel für Ulmeneffekte einen zweiten Würfel hinzu?

Es ist eine Follow-up Herausforderung darin, eine zweite Düse hinzuzufügen das Beispiel, so dass ein einzelner Klick auf den Button einen neuen Wert für jeden Würfel wirft. Meine Idee ist es, das Modell zu ändern zwei getrennte Werte zu halten, einen für jeden sterben, ala

type alias Model = 
     { dieFace1 : Int 
     , dieFace2 : Int 
     } 

Das funktioniert gut, bis ich zum Update-Block erhalten. Ich bin mir nicht sicher, wie ich den Zufallszahlengenerator aktualisieren soll, um zwei Werte zu erzeugen. Die Funktion ist für mich etwas verwirrend.

type Msg 
    = Roll 
    | NewFace Int Int 


update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
    case msg of 
    Roll -> 
     **(model, Random.generate NewFace (Random.int 1 6))** <-- not sure what to do here 

    NewFace newFace1 newFace2 -> 
     (Model newFace1 newFace2, Cmd.none) 

Die Dokumentation für die Random.generate Funktion ist ein wenig Licht -

erzeugen: (a -> msg) -> Generator a -> Cmd msg

Bewirkt dass erzeugt zufällige Werte.

Ist das sogar der richtige Ansatz, um zwei Würfel zu bearbeiten, oder gibt es einen besseren Weg? Ich bin ein Ulm noob, bitte sei nett :)

Antwort

13

Random.int ist ein primitiver Generator, der Ihnen eine einzige zufällige int gibt. Sie benötigen einen Generator, der Ihnen genau zwei zufällige Ganzzahlen gibt.

Zufallsgeneratoren können aus primitiveren Generatoren aufgebaut werden, um komplexere Generatoren zu erzeugen. Glücklicherweise hat Elm genau diese Funktion, Random.pair, mit der Sie angeben können, welche zwei Generatoren Sie für jeden Teil des Tupels benötigen.

Lassen Sie uns den Formgenerator in seine eigene Funktion ziehen uns nicht zu wiederholen:

dieGenerator : Random.Generator Int 
dieGenerator = 
    Random.int 1 6 

Jetzt können wir einen weiteren Generator bauen, die uns den Zufallswert eines Paares von Form gibt:

diePairGenerator : Random.Generator (Int, Int) 
diePairGenerator = 
    Random.pair dieGenerator dieGenerator 

Da es sich um ein Tupel von Ints handelt, aktualisieren wir Ihre Msg Definition von NewFace Int Int zu NewFaces (Int, Int). Das erlaubt Ihrem Roll Handler schön und sauber zu sein:

Roll -> 
    (model, Random.generate NewFaces diePairGenerator) 

Wenn Sie darüber hinaus versuchen wollen bewegen, darüber nachzudenken, was es dauern würde, für eine beliebige Anzahl von Düse ermöglichen gerollt werden. Nehmen Sie diese Idee des Aufbaus komplexer Generatoren aus primitiveren Generatoren und verwenden Sie die Dokumentation für das Modul Random uns eine Anleitung.

+0

Super, danke für die Zeiger auf den richtigen Teil der Dokumentation, auch. Es sieht so aus, als würde die Anzahl der Würfelwürfe eine Zufallsliste von Random.ints parametrisieren, um die Anzahl der gewünschten Würfel zu enthalten, denke ich. Danke für die Antwort und die neuen Hausaufgaben. – TonyM

+1

Danke Tschad für die Erklärung im Detail. Lief wie am Schnürchen. Ich habe einen Grund für die faulen: https://gist.github.com/dotcs/3b3626cfbe5b0744134f7af8edcb32c5 – dotcs

+1

Wie sieht die Lösung aus, wenn wir nicht erwarten, ein Tupel von 'Int', aber _zwei_' Int' Parameter? I.e. Wenn "Msg" definiert ist als "NewFaces Int Int", wie vom OP erkannt? –

1

Ein Ansatz ist die Verwendung batch wie hier https://gist.github.com/davidchase/40c27042bccfb00d786af0360b5bc3ea.

Ein weiterer Grund ist Random.pair oder Random.list zu verwenden, wenn Sie mehr als 2 benötigen:

import Html exposing (..) 
import Html.App as Html 
import Html.Events exposing (..) 
import Html.Attributes exposing (..) 
import Random 


main : Program Never 
main = 
    Html.program 
    { init = init 
    , view = view 
    , update = update 
    , subscriptions = subscriptions 
    } 

-- MODEL 

type alias Model = 
    { dieFaces : (List Int) 
    } 

-- http://stackoverflow.com/questions/23199398/how-do-i-get-a-list-item-by-index-in-elm#comment56252508_23201661 
get : Int -> List a -> Maybe a 
get n xs = List.head (List.drop n xs) 

-- http://rundis.github.io/blog/2016/elm_maybe.html 
getOrOne : Int -> List Int -> Int 
getOrOne n xs = Maybe.withDefault 1 (get n xs) 

init : (Model, Cmd Msg) 
init = 
    (Model [1, 1], Cmd.none) 

-- UPDATE 

type Msg 
    = Roll 
    | NewFace (List Int) 

update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
    case msg of 
    Roll -> 
     (model, Random.generate NewFace (Random.list 2 (Random.int 1 6))) 

    NewFace newFace -> 
     (Model newFace, Cmd.none) 

-- SUBSCRIPTIONS 

subscriptions : Model -> Sub Msg 
subscriptions model = 
    Sub.none 

-- VIEW 

view : Model -> Html Msg 
view model = 
    div [] 
    [ img [ src ("/img/Alea_" ++ toString (getOrOne 0 model.dieFaces) ++ ".png")] [] 
    , img [ src ("/img/Alea_" ++ toString (getOrOne 1 model.dieFaces) ++ ".png")] [] 
    , button [ onClick Roll ] [ text "Roll" ] 
    ] 

und andere https://github.com/jcollard/random-examples/blob/master/src/Dice.elm

Verwandte Themen