RosettaCodeData/Task/Rock-paper-scissors/Perl/rock-paper-scissors-1.pl
2015-02-20 00:35:01 -05:00

121 lines
3.3 KiB
Perl

use 5.012;
use warnings;
use utf8;
use open qw(:encoding(utf-8) :std);
use Getopt::Long;
package Game {
use List::Util qw(shuffle first);
my $turns = 0;
my %human_choice = ( rock => 0, paper => 0, scissors => 0, );
my %comp_choice = ( rock => 0, paper => 0, scissors => 0, );
my %what_beats =
( rock => 'paper', paper => 'scissors', scissors => 'rock', );
my $comp_wins = 0;
my $human_wins = 0;
my $draws = 0;
sub save_human_choice {
my $ch = lc pop;
if ( exists $human_choice{ $ch } ) {
++$human_choice{ $ch };
}
else {
die __PACKAGE__ . ":: wrong choice: '$ch'";
}
}
sub get_comp_choice {
my @keys = shuffle keys %human_choice;
my $ch;
my ( $prob, $rand ) = ( 0, rand );
$ch = ( first { $rand <= ( $prob += ( $human_choice{ $_ } / $turns ) ) } @keys )
if $turns > 0;
$ch //= $keys[0];
$ch = $what_beats{ $ch };
++$comp_choice{ $ch };
return $ch;
}
sub make_turn {
my ( $comp_ch, $human_ch ) = ( pop(), pop() );
++$turns;
if ( $what_beats{ $human_ch } eq $comp_ch ) {
++$comp_wins;
return 'I win!';
}
elsif ( $what_beats{ $comp_ch } eq $human_ch ) {
++$human_wins;
return 'You win!';
}
else {
++$draws;
return 'Draw!';
}
}
sub get_final_report {
my $report =
"You chose:\n"
. " rock = $human_choice{rock} times,\n"
. " paper = $human_choice{paper} times,\n"
. " scissors = $human_choice{scissors} times,\n"
. "I chose:\n"
. " rock = $comp_choice{rock} times,\n"
. " paper = $comp_choice{paper} times,\n"
. " scissors = $comp_choice{scissors} times,\n"
. "Turns: $turns\n"
. "I won: $comp_wins, you won: $human_wins, draws: $draws\n";
return $report;
}
}
sub main {
GetOptions( 'quiet' => \my $quiet );
greet() if !$quiet;
while (1) {
print_next_line() if !$quiet;
my $input = get_input();
last unless $input;
if ( $input eq 'error' ) {
print "I don't understand!\n" if !$quiet;
redo;
}
my $comp_choice = Game::get_comp_choice();
Game::save_human_choice($input);
my $result = Game::make_turn( $input, $comp_choice );
describe_turn_result( $input, $comp_choice, $result )
if !$quiet;
}
print Game::get_final_report();
}
sub greet {
print "Welcome to the Rock-Paper-Scissors game!\n"
. "Choose 'rock', 'paper' or 'scissors'\n"
. "Enter empty line or 'quit' to quit\n";
}
sub print_next_line {
print 'Your choice: ';
}
sub get_input {
my $input = <>;
print "\n" and return if !$input; # EOF
chomp $input;
return if !$input or $input =~ m/\A \s* q/xi;
return
( $input =~ m/\A \s* r/xi ) ? 'rock'
: ( $input =~ m/\A \s* p/xi ) ? 'paper'
: ( $input =~ m/\A \s* s/xi ) ? 'scissors'
: 'error';
}
sub describe_turn_result {
my ( $human_ch, $comp_ch, $result ) = @_;
print "You chose \u$human_ch, I chose \u$comp_ch. $result\n";
}
main();