Skip to content

Instantly share code, notes, and snippets.

@Heimdell
Last active April 14, 2016 13:48
Show Gist options
  • Save Heimdell/237dd4bef2ede8790fa88def710d41ed to your computer and use it in GitHub Desktop.
Save Heimdell/237dd4bef2ede8790fa88def710d41ed to your computer and use it in GitHub Desktop.
import Dict exposing (Dict)
import Maybe exposing (withDefault)
import String
import Text
import Signal
import Keyboard
import Char
import Graphics.Element as Element exposing (Element)
import Graphics.Collage as Collage exposing (Form)
type Player = X | O
other player = case player of
X -> O
O -> X
type alias Point = (Int, Int)
type alias GameState =
{ table : Dict Point Player
, winner : Maybe Player
, player : Player
}
type Move = Put {at : Point} | Clear
put : Move -> GameState -> GameState
-- | Main reducer
put move gs =
case move of
Clear ->
initialState
Put {at} ->
let
-- check if there is nothing at destination
possible = isNothing <| Dict.get at gs.table
in
if possible
then
{ gs | table = Dict.insert at gs.player gs.table
, player = other gs.player }
else
gs
winnerOf _ = Nothing
isNothing : Maybe a -> Bool
-- | Evans, why the heck this function is not in the stdlib?
isNothing it = case it of
Just it -> False
Nothing -> True
isJust : Maybe a -> Bool
-- | Evans, why the heck this function is not in the stdlib?
isJust = not << isNothing
cross = Element.image 20 20 "http://akkompaniator.com/wp-content/uploads/2008/11/vau.jpg"
zero = Element.image 20 20 "http://akkompaniator.com/wp-content/uploads/2009/08/7.jpg"
void = Element.image 20 20 "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Saturn_symbol.svg/170px-Saturn_symbol.svg.png"
properView : GameState -> Element
-- | Main view
properView gs =
let
point (x, y) =
let (y', x') = ((1 - toFloat x) * 20, (toFloat y - 1) * 20)
in Collage.move (x', y')
<| Collage.toForm
<| case Dict.get (x, y) gs.table of
Just X -> cross
Just O -> zero
Nothing -> void
in Collage.collage 60 60
<| List.map point
<| [ (0, 0), (0, 1), (0, 2)
, (1, 0), (1, 1), (1, 2)
, (2, 0), (2, 1), (2, 2)
]
initialState : GameState
initialState =
{ table = Dict.empty
, winner = Nothing
, player = X
}
transcode : List (comparable, to) -> comparable -> Maybe to
-- | Convert dictionary into partial function
transcode list x = Dict.get x (Dict.fromList list)
steps : Signal Move
-- | Main input stream (all moves)
steps
= Keyboard.presses
-- keypress signal is (Signal KeyCode), let convert it to (Signal Char)
|> Signal.map Char.fromCode
-- convert Signal Char -> Signal (Maybe Move)
|> Signal.map (transcode
[ ('1', Put {at = (0, 0)})
, ('2', Put {at = (0, 1)})
, ('3', Put {at = (0, 2)})
, ('4', Put {at = (1, 0)})
, ('5', Put {at = (1, 1)})
, ('6', Put {at = (1, 2)})
, ('7', Put {at = (2, 0)})
, ('8', Put {at = (2, 1)})
, ('9', Put {at = (2, 2)})
, (' ', Clear)
])
-- throw out all "Nothing"s
|> Signal.filter isJust Nothing
-- unwrap Signal (Maybe Move) -> Signal Move
|> Signal.map (withDefault (Put {at = (0, 0)}))
states : Signal GameState
states = Signal.foldp put initialState steps
main : Signal Element
main = Signal.map properView states
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment