榆树指导骰子练习

问题描述

我正在执行随机部分的 Elm 指南练习,但在第 5 步中卡住了,我必须在骰子确定最终值之前翻转骰子。我正在尝试调用 Cmd 来执行此操作,该 Cmd 会使用骰子的新值更新视图,只需单击“Roll!”按钮即可更新 10 次。并在每次迭代之前放置某种睡眠功能。据我所知,Elm 没有 for、循环或 while 语句。循环的唯一方法是通过递归,但我无法调整我的代码。我的代码如下,有人有建议吗?

import browser
import Html exposing (..)
import Html.Events exposing (..)
import Svg exposing (..)
import Svg.Attributes as SvgAttr exposing (..)
import Random



-- MAIN


main =
  browser.element
    { init = init,update = update,subscriptions = subscriptions,view = view
    }



-- MODEL


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


init : () -> (Model,Cmd Msg)
init _ =
  ( Model 1 1,Cmd.none
  )



-- UPDATE


type Msg
  = Roll
  | NewFace (Int,Int)


update : Msg -> Model -> (Model,Cmd Msg)
update msg model =
  case msg of
    Roll ->
      ( model,Random.generate NewFace randomPair
      )

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

weightedRoll : Random.Generator Int
weightedRoll =
  Random.weighted
          (1,1)
          [ (10,2),(10,3),4),(20,5),(40,6)
          ]
          
          
randomPair : Random.Generator (Int,Int)
randomPair = 
  Random.pair (Random.int 1 6) (Random.int 1 6)
    
    
  
    

-- SUBSCRIPTIONS


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



-- VIEW


view : Model -> Html Msg
view model =
  div [] 
      [ h1 [] [ Html.text (String.fromInt model.dieFace) ],svg
          [ width "120",height "120",viewBox "0 0 120 120"
          ]
        (List.append
          [ rect
            [ x "10",y "10",width "100",height "100",rx "15",ry "15"
            ]
            []
          ]
          (dicesSVG model.dieFace)
        ),div []
            [ h1 [] [Html.text (String.fromInt model.dieFace2) ],ry "15"
            ]
            []
          ]
          (dicesSVG model.dieFace2)
        )],button [onClick Roll] [Html.text "Roll!"]
      ]
    
    
dicesSVG : Int -> List (Svg Msg)
dicesSVG number =
  case number of
    1 ->
      [ circle [cx "60",cy "60",r "10",fill "white" ] [] ]
      
    2 ->
      [ circle [ cx "35",cy "35",fill "white" ] [],circle [ cx "85",cy "85",fill "white" ] []
      ]
      
    3 ->
      [ circle [ cx "35",circle [ cx "60",fill "white" ] []
      ]
      
    4 ->
      [ circle [ cx "35",circle [ cx "35",fill "white" ] []
      ]
      
    5 ->
      [ circle [ cx "35",fill "white" ] []
      ]
      
    6 ->
      [ circle [ cx "35",fill "white" ] []
      ]
      
    _ ->
      []

解决方法

诀窍主要在于要求运行时向您发送消息。

你可以尝试的第一件事是改变

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

  NewFace (newFace,Random.generate NewFace randomPair
      )

这存在永不停止的问题,让你的程序永远旋转......

因此您需要跟踪一些停止条件。也许在您的模型中添加一个字段来跟踪它已经滚动了多少次?然后根据该字段在 Random.generateCmd.none 之间切换。


最后,如果你想要两次滚动之间的时间延迟,那么

import Task


wait : Float -> msg -> Cmd msg
wait delay msgToCallWhenDone =
  Task.perform (always msg) (Process.sleep delay)

会给你一个 Cmd,它会在 delay 毫秒后调用你给它的任何 msg。作为提示,您可能想为此引入另一个 msg。