yopisan
@yopisan (kota)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ポーカー役判定うまく表示できない

ポーカーの表示が思い通りにいかないので、どなたかご教授お願いいたします。

(ルール)
// 「algorithm5」で作成したポーカープログラムにジョーカーを追加してください。
// ジョーカー1枚のみ、suitをjoker、numberを0と表す。
// 上記以外は不正として処理してください。

// 追加された役
// 「フォーカード」+ジョーカーは「ファイブカード」

// 判定は強い役を優先してください。組み合わせの強さ順は以下とする。
// ロイヤルストレートフラッシュ > ストレートフラッシュ > ファイブカード > フォーカード > フルハウス > フラッシュ > ストレート > スリーカード > ツーペア > ワンペア
// ジョーカーが出た時点で最低でも「ワンペア」となること

一つ目
https://i.gyazo.com/270b0cd8b60a20b7c04b349337fbe19d.png
こちらはこちらは、ストレートフラッシュになるのが正解です。
ですが役なしと表示されてしまう。

二つ目
https://gyazo.com/3598d5d09a8d7469ce24de8eff44cb39
こちらは、不正になるのが正解です。
なぜなら、カードの数は13以上の数字が存在しないから。

該当するソースコード

 $cards = [
      ['suit'=>'heart', 'number'=>15],
      ['suit'=>'spade', 'number'=>15],
      ['suit'=>'joker', 'number'=>0],
      ['suit'=>'diamond', 'number'=>20],
      ['suit'=>'club', 'number'=>20],
    ];
 

  function judge($cards) {
    //絵札の枚数
    $cards_suit = array_column($cards,'suit');
    $count_suit = array_count_values($cards_suit);
  
    //ストレートの時の手札
    $cards_num = array_column($cards,'number');
    $num_min = $cards_num[0];
    $str_num = range($num_min , $num_min+4);
    $j_num_min = $cards_num[2];
    $j_str_num = [$j_num_min-1,$j_num_min,$j_num_min+1,$j_num_min+2,$j_num_min+3];
  
    //数字の枚数
    $count_num = array_count_values($cards_num);
  
    //ロイヤルストレートフラッシュの数字
    $royal = [1,10,11,12,13];
  
  
    // カードの不正チェック
   
      if (count(array_unique($cards,SORT_REGULAR)) < 5) {
        return "不正";
      }
      elseif ((count(array_keys($cards_suit,'joker'))) >= 2) {
        return "不正";
      }
      elseif ((count(array_keys($cards_suit,'joker'))) >= 2) {
        return "不正";
      }
      elseif ((count(array_keys($cards_num,0))) >= 2) {
        return "不正";
      }
    
    // カードの並び替え
    foreach( $cards as $value) {
      $suit_cards[] = $value['suit'];
      $number_cards[] = $value['number'];
    }
    array_multisort($number_cards, SORT_ASC, SORT_REGULAR, $cards);
  
//  判定
    if (in_array(['suit'=>'joker', 'number'=>0], $cards)){
      if ((count(array_intersect($royal,$cards_num)) == 4) && (count($count_suit) == 4)) {
        return "ロイヤルストレートフラッシュ";
      }
      elseif ((count(array_intersect($j_str_num,$cards_num)) == 4) && (count($count_suit) == 2)){
         return "ストレートフラッシュ";
        
      }
      elseif (count($count_num) == 2) {
        return "ファイブカード";
      }
      elseif ((count($count_num) == 3) && (max($count_num) == 3)) {
        return "フォーカード";
      }
      elseif (count($count_num) == 3) {
        return "フルハウス";
      }
      elseif (count(array_intersect($j_str_num,$cards_num)) == 4) {
        return "ストレート";
      }
      elseif (count($count_suit) == 2) {
        return "フラッシュ";
      }
      elseif (count($count_num) == 4) {
        return "スリーカード";
      }
      else {
        return "ワンペア";
      }
    }
    else {
    if (($cards_num == [1,10,11,12,13]) && (count(array_unique($cards_suit)) == 1)) {
        return "ロイヤルストレートフラッシュ";
      }
      elseif (($cards_num == $str_num) && (count(array_unique($cards_suit)) == 1)) {
        return "ストレートフラッシュ";
      }
      elseif (array_keys($count_num,4)) {
        return "フォーカード";
      }
      elseif (count($count_num) == 2) {
        return "フルハウス";
      }
      elseif (count($count_suit) == 1) {
        return "フラッシュ";
      }
      elseif ($cards_num == $str_num) {
        return "ストレート";
      }
      elseif ((count($count_num) == 3) && (array_keys($count_num,3))) {
        return "スリーカード";
      }
      elseif (count($count_num) == 3) {
        return "ツーペア";
      }
      elseif (count($count_num) == 4) {
        return "ワンペア";
      }
      else {
        return "なし";
      }
    }
  }
  
  ?>
  <!DOCTYPE html>
  <html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>ポーカー役判定(ジョーカーあり)</title>
  </head>
  <body>
    <section>
      <p>手札は</p>
      <p><?php foreach($cards as $card): ?><?=$card['suit'].$card['number'] ?><?php endforeach; ?></p>
      <p>役は<?=judge($cards) ?>です。</p>
    </section>
  </body>
  </html>

自分で試したこと

自分で試したこととして
一つ目は
elseif ((count(array_intersect($j_str_num,$cards_num)) == 5) && (count($count_suit) == 2)){
return "ストレートフラッシュ";
}
の($j_str_num,$cards_num)) == 5) の数字を5に変えたなぜなら、同じマークかつ連番のため単純に5に変えるだけなのかなと思い変えた

二つ目はカードの不正チェックに
foreach($cards as $card){
if($card['number']> 13 || $card['number'] < 0){
return "手札が不正";
}
コードを入れ込んだら解消されるかと思い取り組んだが、Unexpected 'EndOfFile'.syntax error, unexpected end of fileが表示されているので、
}を付け足したりしたがエラーは解消されませんでした。

長々となりましたが、これらの条件にあうコードやアドバイスなどお願いいたします。

0

3Answer

ジョーカーがある場合、ソートした手札に対してジョーカーを1~13に変化させて手札が連番になっているか調べる。

私もこれが簡単にできる方法だと思います。

J(1),3,5,6,7
J(2),3,5,6,7
J(3),3,5,6,7
3,J(4),5,6,7

もっとスマートな方法があるかもしれませんが、まずは動くことを優先で。

@yulianess23

1,2,3,4,5もストレートになるようです。
ローカルルールなどあるかもしれないですが。

同じAを含むストレートでも 5♠ 4♦ 3♦ 2♠ A♥ は「5-ハイ ストレート」(Wheelとも呼ばれる[3])は、ストレートの中で最も弱い。

1Like

Comments

  1. @yopisan

    Questioner

    なるほどですね。
    ありがとうございます。
    参考に直してみたら、ストレートフラッシュとロイヤルストレートフラッシュについて解決いたしました。 

質問に答える前にですが、画像は外部サイトではなく直接貼り付けた方が良いです。
文章中に記述されているコードの表示が正しくないので、$value = 1のように文章中にコードを記述する場合は改行なしの```で括ると見やすくなります。


ストレートフラッシュは「数字がすべて連続している(ただし1は13と連続する)」かつ「スートが全て同じ」です。
これを判定するためにはどうすればいいか考えましょう。

まず、コードについてですが、$cards_numはソートされていないので $num_min = $cards_num[0]は最小値ではありません。
配列の最小値をとるならmin()を使うべきですが、ジョーカー(0)がある場合にもやはり最小値はとれません。

array_intersect は配列の共通項を得る関数です。
なので、array_intersect([1,1,2,3,10], [1,2,3,4,5])でも結果の要素数が4になってしまい、考慮不足です。


ストレートの判定は、私が考えるだけ、(好ましい処理かどうかはさておき)以下の判定方法を思いつきます。

  • ジョーカーがない場合、「2,3,4,5,6」~「10,11,12,13,A」の全手探索を行う。
    (ジョーカーがある場合でも45手以下の探索。手数を減らすには少し工夫が必要)
  • 手札からジョーカーを除去し、ペアが一つもなく、かつ、1を14として考え、手札の最大値と最小値の差が4以下である。
  • 手札からジョーカーを除去し、手札の最小値をとり、「最小値~最小値+4(13を超える場合は1に戻る)」の配列をつくり、手札と一致する数値を配列から除去しながら手札全てと同じ数値が存在するか調べる。
  • ジョーカーがある場合、ソートした手札に対してジョーカーを1~13に変化させて手札が連番になっているか調べる。

フラッシュの判定は単純にスートの個数を見ればいいし、すでにarray_count_valuesを使っているので言うこともないのですが、

  • ジョーカーがない場合、全てのスートが等しいか調べる
  • ジョーカーがない場合、スートの種類が1種類(array_count_valuesの要素数が1)
  • ジョーカーがある場合、スートの種類が2種類(ジョーカーを5種目のスートとして見れば)

なお、どんなストレートチェックでも「1,2,3,4,5」がストレートでないことは考慮が必要です。

(追記)

@blue32a

「1,2,3,4,5」もストレートなんですね・・・調べた感じそれがローカルルールということもなさそうなので、単に私が知らなかっただけと認識します。
(上記の記述は打消し線とします)

0Like

Comments

  1. @yopisan

    Questioner

    ありがとうございます。
    参考に直してみたら、ストレートフラッシュとロイヤルストレートフラッシュについて解決いたしました。
  2. @yopisan

    Questioner

    ありがとうございます。
    参考に直してみたら、ストレートフラッシュとロイヤルストレートフラッシュについて解決いたしました。 
elseif ((count(array_intersect($j_str_num,$cards_num)) == 4) && (count($count_suit) == 2)){

KingからAceへのつながりが考慮されていないような?

あとストレートフラッシュは絵柄2種類じゃなくて1種類じゃないでしょうか

0Like

Comments

  1. @yopisan

    Questioner

    ありがとうございます。
    参考に直してみたら、ストレートフラッシュとロイヤルストレートフラッシュについて解決いたしました。

Your answer might help someone💌