Writing A Word Memory Game In Elm - Part 5: More Randomness And More Game
Mickey
Posted on May 31, 2019
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.
Posted on May 31, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 28, 2024