Skip to content

Instantly share code, notes, and snippets.

@smsohan
Created March 21, 2011 22:23
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 smsohan/880357 to your computer and use it in GitHub Desktop.
Save smsohan/880357 to your computer and use it in GitHub Desktop.
F# code that simulates a lawn tennis game points
#light
open System
type Game()=
member this.NewScore(winnersScore, othersScore)=
match winnersScore with
|"0" -> "15", othersScore
|"15" -> "30", othersScore
|"30" -> "40", othersScore
|"40" when othersScore = "A" -> "40", "40"
|"40" when othersScore = "40"-> "A", "40"
|"40" -> "Won", othersScore
|"A" -> "Won", othersScore
|_ -> failwith "Invlaide Score"; "0", "0"
member this.ChangeScore(score, playerNumber)=
match playerNumber, score with
|_, ("Won", _) | _, (_, "Won") -> score
| 1, (winner, other) -> this.NewScore(winner, other)
| 2, (other, winner) -> this.NewScore(winner, other) |> fun(a, b) -> (b, a)
|_ -> failwith "Invalid player"; ("0", "0")
member this.Play()=
let rec recPlay score=
let playerOwn = ((new System.Random()).Next(2) + 1 )
match score with
|("Won", _) | (_, "Won") -> score
|_ ->
printfn "%A" score
printf "P%d\t" playerOwn
recPlay (this.ChangeScore(score, playerOwn))
recPlay("0", "0")
type Set()=
member this.TieBreak(score)=
match ((new System.Random()).Next(2) + 1 ), score with
|1, (p1, p2) -> (p1 + 1, p2)
|2, (p1, p2) -> (p1, p2+1)
|_ -> failwith "TieBreak Error"; (0, 0)
member this.NewGame(p1Score, p2Score)=
let result = (new Game()).Play()
printfn "%A" result
match result with
|("Won", _) -> (p1Score + 1, p2Score)
|(_, "Won") -> (p1Score, p2Score + 1)
|_ -> failwith "Incomplete Game!";(0,0)
member this.Play()=
let rec recPlay(p1Score, p2Score)=
let (newP1Score, newP2Score) = this.NewGame(p1Score, p2Score)
printfn "Set: %A" (newP1Score, newP2Score)
if(newP1Score = 6 && newP2Score = 6) then
this.TieBreak((newP1Score, newP2Score))
elif (newP1Score > 5 && (newP1Score - newP2Score) >= 2) || (newP2Score > 5 && (newP2Score - newP1Score) >= 2) then
(newP1Score, newP2Score)
else recPlay(newP1Score, newP2Score)
recPlay(0, 0)
type Match(minWins)=
let _minWins = minWins
member this.IsOver(sets: list<int * int>)=
match this.WhoWon(sets) with
|Some(_) -> true
|None -> false
member this.NewSet()=
(new Set()).Play()
member this.Play()=
let rec recPlay(sets: list<int*int>)=
let newSets = List.append sets [this.NewSet()]
match this.IsOver(newSets) with
| true -> newSets
| false -> recPlay(newSets)
recPlay([])
member this.WhoWon(sets: list<int * int>)=
if sets.Length < minWins then None
else
let p1Sets = List.choose(fun(a,b) -> match (a,b) with
|(x, y) when x > y -> Some(x,y)
| _ -> None) sets
if(p1Sets.Length >= _minWins) then Some(1)
elif((sets.Length - p1Sets.Length) >= _minWins) then Some(2)
else None
printf "Start\t"
let m = new Match(3)
let sets = m.Play()
let winner = sets |> m.WhoWon
printfn "%A %A" winner sets
ignore(Console.ReadLine())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment