21 game: Difference between revisions

Add F# version
m (→‎{{header|REXX}}: fixed a comment by re-aligning it.)
(Add F# version)
Line 2,202:
Running total: 21
+human+ wins!
</pre>
 
=={{header|F sharp|F#}}==
<lang fsharp>
type Player =
| Computer
| Person
type Play = {runningTotal:int; nextTurn:Player}
type Win =
| ByExact of Player
| ByOtherExceeded of Player
type Status =
| Start
| Playing of Play
| Winner of Win
| Exit
 
let rnd = System.Random ()
let randomFirstPlayer () =
let selection = rnd.Next 2
if selection = 0 then Computer else Person
let computerChose current =
if current > 17 then 21-current // win strategy
else if current > 13 && current < 17 then 17-current // naive thwart opponent strategy
else rnd.Next(1, (min 4 (21-current+1)))
 
let (|Exact|Exceeded|Under|) i = if i = 21 then Exact else if i > 21 then Exceeded else Under
let (|ValidNumber|InvalidInput|Quit|) (s:string) =
let trimmed = s.Trim().ToLower()
if trimmed = "1" || trimmed = "2" || trimmed = "3" then ValidNumber
else if trimmed = "q" then Quit
else InvalidInput
let readable = function | Computer -> "Computer is" | Person -> "You are"
 
let rec looper = function
| Start ->
let firstPlayer = randomFirstPlayer ()
printfn $"{readable firstPlayer} randomly selected to go first."
looper (Playing {runningTotal=0; nextTurn=firstPlayer})
| Playing play ->
match play with
| {runningTotal=Exact; nextTurn=Person} -> looper (Winner (ByExact Computer))
| {runningTotal=Exact; nextTurn=Computer} -> looper (Winner (ByExact Person))
| {runningTotal=Exceeded; nextTurn=player} -> looper (Winner (ByOtherExceeded player))
| {runningTotal=r; nextTurn=player} ->
match player with
| Computer ->
let computerChoice = computerChose r
let total = r+computerChoice
printfn $"Computer entered {computerChoice}. Current total now: {total}."
looper (Playing {runningTotal=total; nextTurn=Person})
| Person ->
let input = printf "Enter number 1, 2, or 3 (or q to exit): "; System.Console.ReadLine ()
match input with
| ValidNumber ->
let playerChoice = System.Int32.Parse input
let total = r+playerChoice
printfn $"Player entered {playerChoice}. Current total now: {total}."
looper (Playing {runningTotal=total; nextTurn=Computer})
| Quit -> looper Exit
| InvalidInput -> printfn "Invalid input. Try again."; looper (Playing play)
| Winner win ->
match win with
| ByExact player -> printfn $"{readable player} the winner by getting to 21."; looper Exit
| ByOtherExceeded player -> printfn $"{readable player} the winner by not exceeding 21."; looper Exit
| Exit -> printfn "Thanks for playing!"
let run () = looper Start
</lang>
{{out}}
<pre>
You are randomly selected to go first.
Enter number 1, 2, or 3 (or q to exit): 5
Invalid input. Try again.
Enter number 1, 2, or 3 (or q to exit): a
Invalid input. Try again.
Enter number 1, 2, or 3 (or q to exit): 3
Player entered 3. Current total now: 3.
Computer entered 3. Current total now: 6.
Enter number 1, 2, or 3 (or q to exit): 3
Player entered 3. Current total now: 9.
Computer entered 1. Current total now: 10.
Enter number 1, 2, or 3 (or q to exit): 2
Player entered 2. Current total now: 12.
Computer entered 2. Current total now: 14.
Enter number 1, 2, or 3 (or q to exit): 1
Player entered 1. Current total now: 15.
Computer entered 2. Current total now: 17.
Enter number 1, 2, or 3 (or q to exit): 2
Player entered 2. Current total now: 19.
Computer entered 2. Current total now: 21.
Computer is the winner by getting to 21.
Thanks for playing!
 
</pre>
 
Anonymous user