Elm中如何为Model内的两个骰子分配不同随机值?
Hey there! Let's get those two dice rolling different numbers instead of matching every time. I'll walk you through the problem and the solution step by step.
What's Causing the Same Value for Both Dice?
Looking at your code, the issue is in how you're generating and applying random numbers:
- When you click "Roll", you're only generating one random number with
Random.generate NewFace (Random.int 1 6) - Then in the
NewFacebranch, you set bothdieFace1anddieFace2to that single value:( Model newFace newFace, Cmd.none )
Naturally, both dice end up identical! We need to generate two independent random numbers and assign each to its own die face.
Step-by-Step Fix
Update the
MsgType
We need a message that can carry two random numbers instead of one. Change yourMsgdefinition to:type Msg = Roll | NewFaces (Int, Int)Generate a Pair of Random Numbers
In theRollbranch ofupdate, useRandom.pairto create two independent 1-6 random values at once:Roll -> ( model, Random.generate NewFaces (Random.pair (Random.int 1 6) (Random.int 1 6)) )Assign Each Random Number to Its Die
Modify theNewFacesbranch to unpack the tuple and assign each value to the correct die face:NewFaces (face1, face2) -> ( Model face1 face2, Cmd.none )
Full Modified Code
Here's the complete code with all changes applied (I've added comments where modifications were made):
import Html exposing (..) import Html.Attributes import Html.Events exposing (..) import List import Random import Svg exposing (..) import Svg.Attributes exposing (..) main = Html.program { init = init , view = view , update = update , subscriptions = subscriptions } -- MODEL type alias Model = { dieFace1 : Int , dieFace2: Int } init : ( Model, Cmd Msg ) init = ( Model 2 5, Cmd.none ) -- UPDATE -- Modified Msg type to carry a pair of integers type Msg = Roll | NewFaces (Int, Int) update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of Roll -> -- Generate a pair of random numbers instead of one ( model, Random.generate NewFaces (Random.pair (Random.int 1 6) (Random.int 1 6)) ) NewFaces (face1, face2) -> -- Assign each random number to its respective die face ( Model face1 face2, Cmd.none ) -- SUBSCRIPTIONS subscriptions : Model -> Sub Msg subscriptions model = Sub.none -- VIEW view : Model -> Html Msg view model = div [] [ h1 [] [ Html.text (toString (model.dieFace1 + model.dieFace2)) ] , svg [ width "120", height "120", viewBox "0 0 120 120", fill "white", stroke "black", strokeWidth "3", Html.Attributes.style [ ( "padding-left", "20px" ) ] ] (List.append [ rect [ x "1", y "1", width "100", height "100", rx "25", ry "25" ] [] ] (svgCirclesForDieFace model.dieFace1) ) , svg [ width "120", height "120", viewBox "0 0 120 120", fill "white", stroke "black", strokeWidth "3", Html.Attributes.style [ ( "padding-left", "20px" ) ] ] (List.append [ rect [ x "1", y "1", width "100", height "100", rx "25", ry "25" ] [] ] (svgCirclesForDieFace model.dieFace2) ) , br [] [] , button [ onClick Roll ] [ Html.text "Roll" ] ] svgCirclesForDieFace : Int -> List (Svg Msg) svgCirclesForDieFace dieFace = case dieFace of 1 -> [ circle [ cx "50", cy "50", r "10", fill "black" ] [] ] 2 -> [ circle [ cx "25", cy "25", r "10", fill "black" ] [] , circle [ cx "75", cy "75", r "10", fill "black" ] [] ] 3 -> [ circle [ cx "25", cy "25", r "10", fill "black" ] [] , circle [ cx "50", cy "50", r "10", fill "black" ] [] , circle [ cx "75", cy "75", r "10", fill "black" ] [] ] 4 -> [ circle [ cx "25", cy "25", r "10", fill "black" ] [] , circle [ cx "75", cy "25", r "10", fill "black" ] [] , circle [ cx "25", cy "75", r "10", fill "black" ] [] , circle [ cx "75", cy "75", r "10", fill "black" ] [] ] 5 -> [ circle [ cx "25", cy "25", r "10", fill "black" ] [] , circle [ cx "75", cy "25", r "10", fill "black" ] [] , circle [ cx "25", cy "75", r "10", fill "black" ] [] , circle [ cx "75", cy "75", r "10", fill "black" ] [] , circle [ cx "50", cy "50", r "10", fill "black" ] [] ] 6 -> [ circle [ cx "25", cy "20", r "10", fill "black" ] [] , circle [ cx "25", cy "50", r "10", fill "black" ] [] , circle [ cx "25", cy "80", r "10", fill "black" ] [] , circle [ cx "75", cy "20", r "10", fill "black" ] [] , circle [ cx "75", cy "50", r "10", fill "black" ] [] , circle [ cx "75", cy "80", r "10", fill "black" ] [] ] _ -> [ circle [ cx "50", cy "50", r "50", fill "red", stroke "none" ] [] ]
How This Works
Random.paircreates a generator that produces two independent random values (each between 1 and 6 in this case)- The
NewFacesmessage carries both values as a tuple - We then unpack the tuple and assign each value to its corresponding die face in the model
Now when you click "Roll", each dice will get its own random number—they might still match occasionally (hey, randomness!) but that's just chance, not a bug.
内容的提问来源于stack exchange,提问作者aThink

