89 lines
2.9 KiB
Factor
89 lines
2.9 KiB
Factor
USING: arrays ascii io kernel math prettyprint random sequences
|
|
strings ;
|
|
IN: rosetta-code.penneys-game
|
|
|
|
! Generate a random boolean.
|
|
: t|f ( -- t/f )
|
|
1 random-bits 0 = ;
|
|
|
|
! Checks whether the sequence chosen by the human is valid.
|
|
: valid-input? ( seq -- ? )
|
|
[ [ CHAR: H = ] [ CHAR: T = ] bi or ] filter length 3 = ;
|
|
|
|
! Prompt the human player for a sequence.
|
|
: input-seq ( -- seq )
|
|
"Please input a 3-long sequence of H or T (heads or tails)."
|
|
print "Example: HTH" print "> " write readln >upper >array ;
|
|
|
|
! Get the human player's input sequence with error checking.
|
|
: get-input ( -- seq )
|
|
t [ drop input-seq dup valid-input? not ] loop ;
|
|
|
|
! Add a random coin flip to a vector.
|
|
: flip-coin ( vector -- vector' )
|
|
t|f CHAR: H CHAR: T ? over push ;
|
|
|
|
! Generate a random 3-long sequence of coin flips.
|
|
: rand-seq ( -- seq )
|
|
V{ } clone 3 [ flip-coin ] times ;
|
|
|
|
! Generate the optimal sequence response to a given sequence.
|
|
: optimal ( seq1 -- seq2 )
|
|
[ second dup CHAR: H = [ CHAR: T ] [ CHAR: H ] if ]
|
|
[ first ] [ second ] tri 3array nip dup
|
|
"The computer chose " write >string write "." print ;
|
|
|
|
! Choose a random sequence for the computer and report what
|
|
! was chosen.
|
|
: computer-first ( -- seq )
|
|
"The computer picks a sequence first and chooses " write
|
|
rand-seq dup >string write "." print >array ;
|
|
|
|
! The human is prompted to choose any sequence with no
|
|
! restrictions.
|
|
: human-first ( -- seq )
|
|
"You get to go first." print get-input ;
|
|
|
|
! Forbid the player from choosing the same sequence as the
|
|
! computer.
|
|
: human-second ( cseq -- cseq hseq )
|
|
get-input [ 2dup = not ]
|
|
[ drop
|
|
"You may not choose the same sequence as the computer."
|
|
print get-input
|
|
] until ;
|
|
|
|
! Display a message introducing the game.
|
|
: welcome ( -- )
|
|
"Welcome to Penney's Game. The computer or the player" print
|
|
"will be randomly selected to choose a sequence of" print
|
|
"three coin tosses. The sequence will be shown to the" print
|
|
"opponent, and then he will choose a sequence." print nl
|
|
"Then, a coin will be flipped until the sequence" print
|
|
"matches the last three coin flips, and a winner" print
|
|
"announced." print nl ;
|
|
|
|
! Check for human victory.
|
|
: human-won? ( cseq hseq coin-flips -- ? )
|
|
3 tail* >array = nip ;
|
|
|
|
! Check for computer victory.
|
|
: computer-won? ( cseq hseq coin-flips -- ? )
|
|
3 tail* >array pick = 2nip ;
|
|
|
|
! Flip a coin until a victory is detected. Then, inform the
|
|
! player who won.
|
|
: flip-coins ( cseq hseq -- )
|
|
"Flipping coins..." print
|
|
rand-seq [ 3dup [ human-won? ] [ computer-won? ] 3bi or ]
|
|
[ flip-coin ] until dup >string print human-won?
|
|
[ "You won!" print ] [ "The computer won." print ] if ;
|
|
|
|
! Randomly choose a player to choose their sequence first.
|
|
! Then play a full round of Penney's Game.
|
|
: start-game ( -- )
|
|
welcome t|f [ human-first dup optimal swap ]
|
|
[ computer-first human-second ] if flip-coins ;
|
|
|
|
start-game
|