Skip to content

Instantly share code, notes, and snippets.

@pdamoc
Created February 9, 2016 08:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdamoc/3c4a4c9564d6235f504c to your computer and use it in GitHub Desktop.
Save pdamoc/3c4a4c9564d6235f504c to your computer and use it in GitHub Desktop.
Guessing Game
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.1 <= v < 3.0.0",
"evancz/elm-html": "4.0.2 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0",
"evancz/start-app": "2.0.2 <= v < 3.0.0",
"lukewestby/elm-string-interpolate": "1.0.0 <= v < 2.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}
module Game where
import Effects exposing (Effects, Never)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import String
import Time
import Task
import Random exposing (generate, int, initialSeed)
import String.Interpolate exposing (interpolate)
-- import RandomNumber exposing (..)
-- MODEL
-- The GameState tracks the current state of the game
type GameState
= Started
| Lost
| Won
| InProgress
type alias Model =
{ mysteryNumber : Int
, maxGuesses : Int
, guessesMade : Int
, gameState : GameState
, inputValue : Int
}
init : (Model, Effects Action)
init =
({ mysteryNumber = 50
, maxGuesses = 10
, guessesMade = 0
, gameState = Started
, inputValue = 0
}, newIntEffect)
{--
randomNumber =
RandomNumber.integerRange
--}
-- UPDATE
type Action
= Guess
| Restart
| EnterText String
| NewMystery Int
newRandIntMB = Signal.mailbox ()
toAction (t, _) =
let
(newInt, _) = generate (int 1 100) (initialSeed (truncate t))
in
NewMystery newInt
newRandIntSignal =
newRandIntMB.signal
|> Time.timestamp
|> Signal.map toAction
newIntEffect =
Signal.send newRandIntMB.address ()
|> Task.map (always (EnterText ""))
|> Effects.task
intOrZero i = String.toInt i |> Result.toMaybe |> Maybe.withDefault 0
noFx model = (model, Effects.none)
update : Action -> Model -> (Model, Effects Action)
update action model =
case action of
Guess ->
let
-- `checkGameState` tells you if the game is InProgress, Lost or Won
checkGameState model =
case (model.guessesMade >= model.maxGuesses, model.inputValue == model.mysteryNumber) of
(True, _) -> Lost
(_, True) -> Won
_ -> InProgress
in
noFx { model
-- Update the guessesMade
| guessesMade = model.guessesMade + 1
-- Check the state of the game
, gameState = checkGameState model
}
-- Capture the input value from the text field in the model. This `EnterText`
-- action is invoked each time the field value changes
EnterText inputValue ->
noFx { model | inputValue = intOrZero inputValue}
-- If the game is restarted, re-initialize the model
NewMystery newInt ->
noFx { model | mysteryNumber = newInt}
Restart ->
init
-- VIEW
view : Signal.Address Action -> Model -> Html
view address model =
div
[]
[ messageDisplay model
, inputField address
, guessButton address model
]
-- The <p> tag that displays the game message
messageDisplay model =
p [] [ text (gameMessage model) ]
-- The <button> that lets the player guess
guessButton address model =
if model.gameState == Started
|| model.gameState == InProgress
then
button [ onClick address Guess ] [ text "guess" ]
else
button [ onClick address Restart ] [ text "restart" ]
-- The <input> text field. It runs the `EnterText` action whenever
-- the
inputField address =
input
[ placeholder "Enter a number..."
, type' "number"
, on "change" targetValue (Signal.message address << EnterText)
]
[]
-- The rest of the following code defines the game display messages
-- the `gameMessage` function displays the correct game text depending on the
-- state of the game
gameMessage model =
let
stateMessage model =
let
stateToString =
if model.gameState == Started || model.gameState == InProgress
then interpolate
", Guess Number: {0} , Max Guesses: {1}"
[toString model.guessesMade , toString model.maxGuesses ]
else ""
in
interpolate
" Your guess: {0}, State: {1}, Mystery Number: {2} {3}"
[ toString model.inputValue
, toString model.gameState
, toString model.mysteryNumber
, stateToString]
in
case model.gameState of
Started ->
"I am thinking of a number between 1 and 100." ++ stateMessage model
InProgress ->
if model.inputValue < model.mysteryNumber then
"That's too low." ++ stateMessage model
else
"That's too high." ++ stateMessage model
Lost ->
"You've run out of guesses! The mystery number was: "
++ toString model.mysteryNumber
++ ". "
++ "Game Over!" ++ stateMessage model
Won ->
"That's correct! It took you: "
++ toString model.guessesMade
++ " guesses. "
++ "Game Over!" ++ stateMessage model
import Effects exposing (Never)
import Game exposing (init, update, view, newRandIntSignal)
import StartApp
import Task
app =
StartApp.start
{ init = init
, update = update
, view = view
, inputs = [newRandIntSignal]
}
main =
app.html
port tasks : Signal (Task.Task Never ())
port tasks =
app.tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment