Strategy

久々のエントリ。もう一つは時間の都合で移し変えず、同じstrategyで勝負しています。

use strict;
use warnings;

{
    package Hand;
    use strict;
    use warnings;
    my $GUU = 0;
    my $CHO = 1;
    my $PAA = 2;
    my $hand = [
        Hand->new($GUU),
        Hand->new($CHO),
        Hand->new($PAA),
                ];
    sub new {
        my ($class, $hand) = @_;
        my $self = {
            hand => $hand,
        };
        return bless $self, $class;
    }
    sub getHand {
        my ($class, $value) = @_;
        return $hand->[$value];
    }
    sub isStrongerThan {
        my ($self, $enemy) = @_;
        return $self->fight($enemy) == 1;
    }
    sub isWeakerThan {
        my ($self, $enemy) = @_;
        return $self->fight($enemy) == -1;
    }
    sub fight {
        my ($self, $enemy) = @_;
        if($self->{hand} == $enemy->{hand}){
            return 0;
        }
        elsif(($self->{hand} + 1) % 3 == $enemy->{hand}){
            return 1;
        }
        else {
            return -1;
        }
    }
}

{
    package Strategy;
    use strict;
    use warnings;
    sub study { die; }
    sub nextHand { die; }
}
{
    package WinningStrategy;
    use strict;
    use warnings;
    our @ISA = qw/Strategy/;
    sub new {
        my($class, $seed) = @_;
        my $self = {
            random   => int(rand($seed)),
            won      => 0,
            prevHand => '',
        };
        return bless $self, $class;
    }
    sub nextHand {
        my $self = shift;
        if(!$self->{won}){
            $self->{prevHand} = Hand->getHand(int(rand(3)));
        }
        return $self->{prevHand};
    }
    sub study {
        my ($self, $result) = @_;
        $self->{won} = $result;
    }
}


{
    package Player;
    use strict;
    use warnings;
    sub new {
        my ($class, $name, $strategy) = @_;
        my $self = {
                name      => $name,
                strategy  => $strategy,
                wincount  => 0,
                losecount => 0,
                gamecount => 0,
            };
        return bless $self, $class;
    }
    sub nextHand {
        my $self = shift;
        return $self->{strategy}->nextHand();
    }
    sub win {
        my $self = shift;
        $self->{strategy}->study(1);
        $self->{wincount}++;
        $self->{gamecount}++;
    }
    sub lose {
        my $self = shift;
        $self->{strategy}->study(0);
        $self->{gamecount}++;
    }
    sub even {
        my $self = shift;
        $self->{gamecount}++;
    }
    sub toString {
        my $self = shift;
        return
            "[".$self->{name}.":".
            $self->{gamecount}." games, ".
            $self->{wincount}." win, ".
            $self->{losecount}." lose]";
    }
}
my @foo = qw/GOO CHO PAA/;
my $player01 = Player->new("Taro", WinningStrategy->new(0));
my $player02 = Player->new("Jiro", WinningStrategy->new(0));

for(1..1000){
    my $nextHand01 = $player01->nextHand();
    my $nextHand02 = $player02->nextHand();

print $foo[$nextHand01->{hand}],"\n";
print $foo[$nextHand02->{hand}],"\n";
    if($nextHand01->isStrongerThan($nextHand02)){
        print "Winner --> ".$player01->{name}."\n";
        $player01->win();
        $player02->lose();
    }
    elsif($nextHand01->isWeakerThan($nextHand02)){
        print "Winner --> ".$player02->{name}."\n";
        $player01->lose();
        $player02->win();
    }
    else {
        print "Even..\n";
        $player01->even();
        $player02->even();
    }
}

print "\n";
print $player01->toString(),"\n";
print $player02->toString(),"\n";