Created
March 21, 2011 22:23
-
-
Save smsohan/880357 to your computer and use it in GitHub Desktop.
F# code that simulates a lawn tennis game points
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
#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