Last active
August 18, 2020 12:59
-
-
Save CraftyFella/243a690f093e25db024e0acf6d7caea9 to your computer and use it in GitHub Desktop.
This file contains 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
open Domain | |
let awardPoint player state = | |
let result = Domain.awardPoint state player | |
printfn "Point to %A. Game is now %A" player result.Score | |
result | |
[<EntryPoint>] | |
let main argv = | |
let player1 = "Foo" | |
let player2 = "Bar" | |
GameState.NewGame player1 player2 | |
|> awardPoint player1 | |
|> awardPoint player2 | |
|> awardPoint player1 | |
|> awardPoint player2 | |
|> awardPoint player2 | |
|> awardPoint player2 | |
|> awardPoint player1 | |
|> awardPoint player2 | |
|> awardPoint player2 | |
|> awardPoint player2 | |
|> ignore | |
0 // return an integer exit code |
This file contains 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
module Domain | |
type Point = | |
| Love | |
| Fifteen | |
| Thirty | |
| Forty | |
type Player = string | |
type Score = | |
| LoveGame | |
| Points of Point * Point | |
| Deuce | |
| Advantage of Player | |
| Game of Player | |
type GameState = | |
{ Player1: Player | |
Player2: Player | |
Score: Score } | |
module GameState = | |
let NewGame p1 p2 = | |
{ Player1 = p1 | |
Player2 = p2 | |
Score = LoveGame } | |
let updateScore (originalScore: Score) (toPlayer: Player) = | |
match originalScore with | |
| LoveGame -> Points(Fifteen, Point.Love) | |
| Game _ -> originalScore | |
| Points (Point.Love, b) -> Points(Fifteen, b) | |
| Points (Point.Fifteen, b) -> Points(Thirty, b) | |
| Points (Thirty, Forty) -> Deuce | |
| Points (Point.Thirty, b) -> Points(Forty, b) | |
| Points (Forty, _) -> Game toPlayer | |
| Deuce -> Advantage toPlayer | |
| Advantage player when player <> toPlayer -> Deuce | |
| Advantage player when player = toPlayer -> Game player | |
let flip (originalScore: Score) = | |
match originalScore with | |
| Points (a, b) -> Points(b, a) | |
| _ -> originalScore | |
let awardPoint (currentScore: GameState) (toPlayer: Player): GameState = | |
match currentScore with | |
| { Player1 = player } when player = toPlayer -> | |
{ currentScore with | |
Score = updateScore currentScore.Score toPlayer } | |
| { Player2 = player } when player = toPlayer -> | |
{ currentScore with | |
Score = flip (updateScore (flip currentScore.Score) toPlayer) } |
No no.. I won't cheat.. I'll take on the comments.. only way to learn.. and attempt to make 40-40 unrepresentable..
Also, just noticed Player
could be better represented
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very nice!
LoveGame
is a redundant state and could be covered byPoints (Love, Love)
(especially since there's no special logic you'll need to switch on to handleLove - Love
).Points (Forty, Forty)
is similarly redundant, though in this case it's better to keepDeuce
as a separate case like you have it because of the special logic associated with it. So then the tricky thing is how to outlaw40 - 40
but still allow40 - 30
, etc. to be represented.(If you want to just see the canonical solution that I like, you can see that here)
Awesome work!