ドロー・ポーカーの Perl プログラム

ドロー・ポーカーの Perl プログラム

以下は、Perl によるドロー・ポーカーのプログラムの一例です。


#!/usr/bin/perl

#役の名称
@hands = ('No Pair',
          'One Pair',
          'Two Pair',
          'Three of a Kind',
          'Straight',
          'Flush',
          'Full House',
          'Four of a Kind',
          'Straight Flush',
          'Royal Straight Flush');

#カードを混ぜる
&shuffle;

#カードを配る
for (0 .. 4) {
  push(@player, shift(@stack));
}

#カードを画面に表示する
&display;

#カードを交換する
&change;

#カードを画面に表示する
&display;

#役を確認する
printf "%s\n", $hands[&check];

#カードを混ぜる
sub shuffle {
  local($index, @flag);

  #擬似乱数を初期化する
  srand:

  #カードを混ぜる
  for (0 .. 51) {#1 組 52 枚のカード
    #未使用カードを探す
    while (1) {
      $index = int(rand(52));
      last if (!$flag[$index]);
    }

    #カードを設定する
    $stack[$_] = $index;

    #フラグを使用済にする
    $flag[$index] = 1;
  }
}

#0 から 51 までの番号をカードに換算する
sub calc {
  local($index, $s, $n);

  $index = $_[0];
  $s     = int($index / 13);
  $n     = $index % 13;
  ($s, $n);
}

#カードを画面に表示する
sub display {
  local($s, $n, @suits);

  #カードの種類
  @suits = ('spade',
            'heart',
            'diamond',
            'club');

  for (0 .. 4) {
    #0 から 51 までの番号をカードに換算する
    ($s, $n) = &calc($player[$_]);

    #カードを画面に表示する
    printf "%s-%d ", $suits[$s], $n + 1;
  }
  printf "\n";
}

#カードを交換する
sub change {
  local($i, @flag);

  #交換するカードを決定する
  while (1) {
    printf "Please select the card(s) you want to change (1 - 5). ";
    printf "To finish, input 0.\n";
    chomp($i = <STDIN>);
    if     ((1 <= $i) && ($i <= 5)) {
      $flag[$i - 1] = 1;
    } elsif ($i eq '0') {
      last;
    } else {
      printf "Input Error!\n";
    }
  }

  #カードを交換する
  for (0 .. 4) {
    $player[$_] = shift(@stack) if ($flag[$_]);
  }
}

#役を確認する
sub check {
  local($i, $j, $s, $n, $flag_f, $flag_s, $flag_3, $npair, @suits, @numbers);

  for (0 .. 4) {
    #0 から 51 までの番号をカードに換算する
    ($s, $n) = &calc($player[$_]);

    #換算したカードの種類と数字の枚数を追加する
    $suits[$s]++;
    $numbers[$n]++;
  }

  #フラッシュ系
  for (0 .. 3) {
    if ($suits[$_] == 5) {
      $flag_f = 1;
      last;
    }
  }

  #ストレート系
  for ($i = 0; $i < 10; $i++) {#ストレートの低位の数字は 1 から 10 まで
    $flag_s = 1;

    for ($j = 0; $j < 5; $j++) {
      if ($numbers[($i + $j) % 13] != 1) {#13 は 1 と連なる
        $flag_s = 0;
        last;
      }
    }

    if ($flag_s == 1) {
      if     (($i == 9) && ($flag_f == 1)) {
        return(9);#ロイヤル・ストレート・フラッシュ
      } elsif ($flag_f == 1) {
        return(8);#ストレート・フラッシュ
      } else {
        return(4);#ストレート
      }
      last;
    }
  }

  return(5) if ($flag_f == 1);#フラッシュ

  #ペア系
  for (0 .. 12) {
    if      ($numbers[$_] == 4) {
      return(7);#フォーカード
    } elsif ($numbers[$_] == 3) {
      $flag_3 = 1;
    } elsif ($numbers[$_] == 2) {
      $npair++;
    }
  }
  if ($flag_3) {
    if ($npair == 1) {
      return(6);#フルハウス
    } else {
      return(3);#スリーカード
    }
  } else {
    if      ($npair == 2) {
      return(2);#ツーペア
    } elsif ($npair == 1) {
      return(1);#ワンペア
    }
  }
  return(0);#ノーペア
}

各ルーチンについて、以下に説明します。