Last active
April 14, 2016 13:48
-
-
Save Heimdell/237dd4bef2ede8790fa88def710d41ed to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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