【问题标题】:How do I add a second die to this elm effects example?如何在此榆树效果示例中添加第二个骰子?
【发布时间】:2016-09-10 16:17:35
【问题描述】:

我是 Elm 的新手,并且一直在查看以下示例(请注意,这是在较新的 0.17 架构下,其中 Action 现在是 Command): http://elm-lang.org/examples/random

有一个后续挑战是在示例中添加第二个骰子,以便单击按钮为每个骰子滚动一个新值。我的想法是更改模型以保存两个单独的值,每个骰子一个,ala

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

这工作正常,直到我到达更新块。我不确定如何更新随机数生成器以创建两个值。这个功能让我有点困惑。

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)

Random.generate 函数的文档有点简单 -

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

创建一个将生成随机值的命令。

这甚至是处理两个骰子的正确方法,还是有更好的方法?我是榆树菜鸟,请善待:)

【问题讨论】:

    标签: elm


    【解决方案1】:

    Random.int 是一个原始生成器,可为您提供单个随机整数。你需要一个能正好给你两个随机整数的生成器。

    随机数生成器可以从更原始的生成器构建,以创建更复杂的生成器。幸运的是,Elm 有这样一个函数,Random.pair,它可以让你为元组的每个部分指定你想要的两个生成器。

    让我们把骰子生成器拉到它自己的函数中以避免重复我们自己:

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

    现在我们可以构建另一个生成器,为我们提供一对骰子的随机值:

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

    由于我们正在处理一个整数元组,让我们将您的 Msg 定义更新为 NewFace Int IntNewFaces (Int, Int)。这将使您的 Roll 处理程序变得干净整洁:

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

    如果您想尝试超越这一点,请考虑允许掷出任意数量的骰子需要什么。采用从更原始的生成器构建复杂生成器的想法,并使用 Random 模块的文档作为指南。

    【讨论】:

    • 太棒了,也感谢您提供指向文档正确部分的指针。我认为,制作 n 次骰子可能涉及参数化 Random.ints 的 Random.list 以包含所需骰子的数量。感谢您的回答和新的作业。
    • 感谢乍得详细解释。像魅力一样工作。我为懒人设置了一个要点:gist.github.com/dotcs/3b3626cfbe5b0744134f7af8edcb32c5
    • 如果我们不期望 Int 的元组,但是 两个 Int 参数,解决方案会是什么样子? IE。如果 Msg 按照 OP 的直觉定义为 NewFaces Int Int
    • 如果您有消息NewFaces2 Int Int,您的update 处理程序可能如下所示:(model, Random.generate (uncurry NewFaces2) diePairGenerator)。函数uncurry 将接受元组参数并将值作为两个参数传递给NewFaces2
    【解决方案2】:

    一种方法是使用batch,就像这里的https://gist.github.com/davidchase/40c27042bccfb00d786af0360b5bc3ea

    另一个是使用Random.pairRandom.list,如果你需要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" ]
        ]
    

    还有一个https://github.com/jcollard/random-examples/blob/master/src/Dice.elm

    【讨论】:

      【解决方案3】:

      除了@ChadGilbert 接受的答案中描述的更改外,我还必须更改NewFaces 更新案例(使用elm 0.18.0)。

      NewFaces newFaces ->
        let
          (newFace1, newFace2) = newFaces
        in
          (Model newFace1 newFace2, Cmd.none)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-16
        • 2019-01-27
        • 1970-01-01
        • 1970-01-01
        • 2016-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多