2016-05-14 14 views
13

Jestem nowy Elm i zostały patrząc na poniższym przykładzie (uwaga ta jest pod nowszej 0,17 architektury, gdzie działanie jest teraz poleceń): http://elm-lang.org/examples/randomJak dodać drugą kość do tego przykładu efektów wiąz?

Jest kontynuacją wyzwanie, aby dodać drugą matrycę przykład, tak aby pojedyncze kliknięcie przycisku rzuciło nową wartość dla każdej kości. Mój pomysł jest zmiana modelu trzymać dwie odrębne wartości, po jednym dla każdej matrycy, ala

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

Działa to dobrze, dopóki nie dostać się do bloku aktualizacji. Nie wiem, jak zaktualizować generator liczb losowych, aby utworzyć dwie wartości. Ta funkcja jest dla mnie nieco dezorientująca.

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) 

Dokumentacja dla funkcji Random.generate jest nieco światła -

generowania: (a -> MSG) -> Generator -> Cmd msg

Utwórz polecenie wygeneruje losowe wartości.

Czy to jest poprawne podejście do obsługi dwóch kostek, czy jest lepszy sposób? Jestem noobem wiązowym, proszę bądź miły :)

Odpowiedz

13

Random.int to prymitywny generator, który daje pojedynczą losową int. Potrzebujesz generatora, który daje dokładnie dwie losowe liczby całkowite.

generatorów liczb losowych może być zbudowany z generatorów bardziej prymitywnych do tworzenia bardziej złożonych generatorów. Na szczęście, Elm ma właśnie taką funkcję, Random.pair który pozwala określić, które dwa generatory chcesz dla każdej części krotki.

Niech wyciągnąć generator matryc do własnej funkcji w celu uniknięcia powtarzania się:

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

Teraz możemy zbudować kolejny generator, który daje nam losową wartość pary umrzeć

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

Ponieważ mamy do czynienia z krotką wskazówki, niech zaktualizować definicję NewFace Int IntMsg do NewFaces (Int, Int). Który pozwoli na Roll teleskopowa być miły i czysty:

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

Jeśli chcesz spróbować wyjść poza to, pomyśl o co zajęłoby pozwalają na dowolną liczbę matrycy być gorąco. Weź tę ideę budowy skomplikowanych generatorów z generatorów bardziej prymitywnych i korzystać z dokumentacji dla Random moduł nam przewodnika.

+0

Awesome, dzięki za wskazówki do właściwej części dokumentacji, zbyt. Wygląda na to, że zrobienie liczby n rzutów może wymagać sparametryzowania Losowej listy Random.intów, aby pomieścić liczbę pożądanych kości. Dzięki za odpowiedź i nową pracę domową. – TonyM

+1

Dziękuję Chadowi za szczegółowe wyjaśnienie. Pracował jak urok. Skonfigurowałem sens dla leniwych: https://gist.github.com/dotcs/3b3626cfbe5b0744134f7af8edcb32c5 – dotcs

+1

Jak wygląda rozwiązanie, jeśli nie oczekujemy krotki parametrów "Int", ale _two_ 'Int'? To znaczy. czy 'Msg' jest zdefiniowany jako' NewFaces Int Int' jako intuicyjny przez OP? –

1

Jednym ze sposobów jest użycie batch, jak tutaj https://gist.github.com/davidchase/40c27042bccfb00d786af0360b5bc3ea.

Innym jest użycie Random.pair lub Random.list jeśli potrzebujesz więcej niż 2:

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" ] 
    ] 

i inny https://github.com/jcollard/random-examples/blob/master/src/Dice.elm

Powiązane problemy