ブラックジャックの Perl プログラム
以下は、Perl によるブラックジャックのプログラムの一例です。
#!/usr/bin/perl
#カードを混ぜる
&shuffle;
while ($#stack > 10) {
undef @PlayerHands;#プレーヤーの手札
undef @DealerHands;#ディーラーの手札
printf "--- Round %d ---\n". ++$nround;
#カードを配る
for (0 .. 1) {
push(@PlayerHands, shift(@stack));
push(@DealerHands, shift(@stack));
}
#合計点数を計算する
$PlayerPoint = &calc(@PlayerHands);
$DealerPoint = &calc(@DealerHands);
#プレーヤーの処理を行う
&player;
#ディーラーの処理を行う
&dealer;
#カードを画面に表示する
&display(1);
}
printf "--- Dealer doesn't have enough cards to continue. ---\n";
#カードを混ぜる
sub shuffle {
local($s);
#擬似乱数を初期化する
srand:
foreach $s ("S", "H", "D", "C") {#1 組 52 枚のカード
for (1 .. 13) {
push(@deck, "$s$_");
}
}
#@deck から 1 枚ずつ @stack に移動する
while ($#deck >= 0) {
push(@stack, splice(@deck, int(rand($#deck + 1)), 1));
}
}
#合計点数を計算する
sub calc {
local(@hands) = @_;
local(@numbers, $point, $na);
#数字を取出す
foreach (@hands) {
$_ =~ /[A-Z](\d+)/;#「アルファベットと 1 文字以上の数字」の数字部分を取出す
push(@numbers, $1);
}
foreach (@numbers) {
if ($_ <= 10) {
$point += $_;
$na++ if ($_ == 1);#A の枚数を数える
} else {#絵札は 10 点
$point += 10;
}
}
if ($point <= 11) {#A は 1 点としても 11 点としてもよい
$point += 10 if ($na);
} elsif ($point >= 22) {#合計点数が 21 点を超えていたら 0 点にする
$point = 0;
}
$point;
}
#カードを画面に表示する
sub display {
local($flag) = @_;
print "PlayerHands : ", join(", ", @PlayerHands), " [$PlayerPoint]\n";
if ($flag == 0) {
print "DealerHands : ", @DealerHands[0], ", ?\n";
} elsif ($flag == 1) {
print "DealerHands : ", join(", ", @DealerHands), " [$DealerPoint]\n";
if ($PlayerPoint == 0) {
printf "Player Busted.\n";
} elsif ($DealerPoint == 0) {
printf "Dealyer Busted.\n";
} elsif ($PlayerPoint > $DealerPoint) {
printf "Player Won.\n";
} elsif ($PlayerPoint < $DealerPoint) {
printf "Dealer Won.\n";
} elsif ($PlayerPoint == $DealerPoint) {
printf "Push.\n";
}
}
}
#プレーヤーの処理を行う
sub player {
local($input);
while (1) {
#カードを画面に表示する
&display(0);
#プレーヤーの処理を行う
printf " Draw(D, d) or Stand(S, s) or Quit(Q, q)? : ";
chop($input = <STDIN>);
if (($input eq "D") || ($input eq "d")) {#カードを引く
printf " Draw\n";
push(@PlayerHands, shift(@stack));
$PlayerPoint = &calc(@PlayerHands);
last if ($PlayerPoint == 0);
} elsif (($input eq "S") || ($input eq "s")) {#カードを引かない
printf " Stand\n";
last;
} elsif (($input eq "Q") || ($input eq "q")) {#終了する
exit;
} else {
printf "Input Error!\n";
}
}
}
#ディーラーの処理を行う
sub dealer {
while ($PlayerPoint) {
last if ($DealerPoint >= 17);#16 でドロー(ヒット)/17 でスタンド(ステイ)
push(@DealerHands, shift(@stack));
$DealerPoint = &calc(@DealerHands);
last if ($DealerPoint == 0);
}
}
各ルーチンについて、以下に説明します。







