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 case
s 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'sStarted
and we added a calculation ofsentence
inside thelet
block. - 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)