This is part 5 of the series "Writing A Word Memory Game In Elm", find:
- Part 1: Setting Up an Elm Application With Parcel
- Part 2: Modeling And Building a Basic Word Memory Game
- Part 3: Rethinking the Model
- Part 4: Spicing Things Up With Randomness
- Part 5 - More Randomness And More Game
Playing with the same sentence all the time is pretty boring. The actual game needs to have many sentences to choose from. For example:
sentences : List String
sentences =
[ "Two wrongs don't make a right."
, "The pen is mightier than the sword."
, "When in Rome, do as the Romans."
, "Keep your friends close and your enemies closer."
, "You can't make an omelet without breaking a few eggs."
, "The grass is always greener on the other side of the hill."
, "You can lead a horse to water, but you can't make him drink."
, "If you want something done right, you have to do it yourself."
]
We can simplify the sentences by removing all the punctuation:
sentences : List String
sentences =
[ "Two wrongs don't make a right"
, "The pen is mightier than the sword"
, "When in Rome do as the Romans"
, "Keep your friends close and your enemies closer"
, "You can't make an omelet without breaking a few eggs"
, "The grass is always greener on the other side of the hill"
, "You can lead a horse to water but you can't make him drink"
, "If you want something done right you have to do it yourself"
]
To choose a sentence at random we can use elm/Random library to generate a random number from 0 to the length of our sentences list and take a sentence at this index (need to convert the List into an Array to use an index).
Or we can use elm-community/random-extra/Random-Extra#sample/ that will choose an element uniformly at random. We already have Random-Extra so let's use it:
import Random.Extra as Random
-- omitted
chooseSentence : List String -> Cmd Msg
chooseSentence sentences_ =
Random.sample sentences_
|> Random.map (Maybe.withDefault "")
|> Random.generate SentenceChosen
In SentenceChosen handler we can call chooseWords command and continue as it was before.
type Msg
= WordChanged Int String
| SentenceChosen String
| WordsChosen (List ( Int, Int ))
| NewGame
We need also to introduce a new state Initialising for modeling the game start:
type GameState
= Initializing
| Started StateStarted
| Playing StatePlaying
| Win StateWin
Now let's implement the SentenceChosen branch of update function:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
-- omitted
SentenceChosen sentenceString ->
case model of
Initializing ->
let
sentence : Words
sentence =
generateSentence sentenceString
in
( Started (StateStarted sentenceString), chooseWords sentence )
Started _ ->
( model, Cmd.none )
Playing _ ->
( model, Cmd.none )
Win _ ->
( model, Cmd.none )
We practically copied the code from the init function. And init itself becomes very short:
init : () -> ( Model, Cmd Msg )
init _ =
( Initializing, chooseSentence sentences )
We set the current state of the game to Initializing and invoke chooseSentence command by passing it the list of sentences.
The compiler informs us about non exhaustive cases for GameState in the update function, so let's address that:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
WordChanged index wordString ->
let
model_ =
case model of
Started { sentence } ->
-- omitted
Initializing ->
model
Started _ ->
model
Win _ ->
model
in
( model_, Cmd.none )
-- omitted
WordsChosen sortIndexes ->
let
model_ =
case model of
Started { currentSentence } ->
let
sentence : Words
sentence =
generateSentence currentSentence
-- omitted
Playing (StatePlaying sentence_)
Initializing ->
model
Playing _ ->
model
Win _ ->
model
in
( model_, Cmd.none )
We made a couple of changes here:
- The first branch was
Playing, now it'sStartedand we added a calculation ofsentenceinside theletblock. - The 3rd branch was
Started, now it'sPlaying.
Thus the flow is more correct:
- Initialiazing - choose random sentence
- Started - choose random words
- Playing
- Win
Now the view function. Let's add a viewInitilizing view:
viewInitializing : Html msg
viewInitializing =
p []
[ text "Initializing..." ]
and call it from view function:
view : Model -> Html Msg
view model =
let
currentView =
case model of
Initializing ->
viewInitializing
Playing { sentence } ->
viewGame sentence
Started { currentSentence } ->
viewStarted currentSentence
Win { currentSentence } ->
viewWin currentSentence
in
main_ [ class "section" ]
[ div [ class "container" ]
[ viewTitle
, div [ class "box" ]
[ currentView ]
]
]
The game compiles and now each time a new game is starting - it picks a random sentence!
The current progress is saved in the repo under a Tag v7.0 https://github.com/mickeyvip/words-memory-game/tree/v7.0.
Stay tuned for Part 6 where we will add a difficulty level and a countdown for the sentence preview.
Top comments (0)