RyotaOsawa
@RyotaOsawa

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!

PHPで書くjokerを含むポーカーでの役判定アルゴリズム。

解決したいこと

役判定のロジックの書き方に行き詰まっています。
jokerがあってもなくても役判定されません。
役判定のロジックの書き方を教えてください。

手札は
heart13 club1 club2 diamond1 club13 
役はなしです

該当するソースコード

<?php

// 手札
$cards = [
    ['suit'=>'heart', 'number'=>13],
    ['suit'=>'club', 'number'=>1],
    ['suit'=>'club', 'number'=>2],
    ['suit'=>'diamond', 'number'=>1],
    ['suit'=>'club', 'number'=>13],
];

// 絵柄の種類
$suits = ['heart', 'diamond', 'spade', 'club'];

// ワイルドカードの joker を定義
$joker = ['suit'=>'joker', 'number'=>0];

function judge($cards, $suits) {
    // ワイルドカードの役判定用フラグ
    $wildcard_used = false;
    foreach ($cards as $card) {
        if ($card['number'] == 0) {
            $wildcard_used = true;
            break;
        }
    }
    
    // ワイルドカードが手札にある場合
    if ($wildcard_used) {
        // ワイルドカードを含めた役判定
        // ここでは各役の条件を優先度順に判定しています
        // 条件に合致する役が見つかった場合、それ以上の役判定は行いません
        if (onePairWithWildcard($cards, $suits)) {
            return "役はワンペアです";
        } elseif (threeCard($cards, $suits)) {
            return "役はスリーカードです";
        } elseif (straight($cards, $suits)) {
            return "役はストレートです";
        } elseif (isFlush($cards, $suits)) {
            return "役はフラッシュです";
        } elseif (fullHouse($cards, $suits)) {
            return "役はフルハウスです";
        } elseif (fourCard($cards, $suits)) {
            return "役はフォーカードです";
        } elseif (straightFlush($cards, $suits)) {
            return "役はストレートフラッシュです";
        } elseif (royalStraightFlush($cards, $suits)) {
            return "役はロイヤルストレートフラッシュです";
        } else {
            return "役はなしです";
        }
    } else {
        // ワイルドカードがない場合の役判定
        if (onePair($cards, $suits)) {
            return "役はワンペアです";
        } elseif (twoPair($cards, $suits)) {
            return "役はツーペアです";
        } elseif (threeCard($cards, $suits)) {
            return "役はスリーカードです";
        } elseif (straight($cards, $suits)) {
            return "役はストレートです";
        } elseif (isFlush($cards, $suits)) {
            return "役はフラッシュです";
        } elseif (fullHouse($cards, $suits)) {
            return "役はフルハウスです";
        } elseif (fourCard($cards, $suits)) {
            return "役はフォーカードです";
        } elseif (straightFlush($cards, $suits)) {
            return "役はストレートフラッシュです";
        } elseif (royalStraightFlush($cards, $suits)) {
            return "役はロイヤルストレートフラッシュです";
        } else {
            return "役はなしです";
        }
    }
}

// ワンペアの判定
function onePair($cards, $suits) {
    $count = array_count_values(array_column($cards, 'number'));
    return count(array_filter($count, function($value) { return $value == 2; })) == 1 && count(array_unique(array_column($cards, 'suit'))) <= count($suits) - 1;
}

// ワイルドカードを含めたワンペアの判定
function onePairWithWildcard($cards, $suits) {
    $count = array_count_values(array_column($cards, 'number'));
    return count(array_filter($count, function($value) { return $value == 2 || $value == 1; })) == 2;
}

// ツーペアの判定(ワンペアと同じ条件なので、ツーペア=スリーカードとなる)
function twoPair($cards, $suits) {
    return onePair($cards, $suits);
}

// スリーカードの判定
function threeCard($cards, $suits) {
    $count = array_count_values(array_column($cards, 'number'));
    return in_array(3, $count) && count(array_unique(array_column($cards, 'suit'))) <= count($suits) - 1;
}

// ストレートの判定
function straight($cards, $suits) {
    $numbers = array_column($cards, 'number');
    sort($numbers);
    return max($numbers) - min($numbers) == 4 && count(array_unique($numbers)) == 5;
}

// フラッシュの判定
function isFlush($cards, $suits) {
    $suitsInHand = array_unique(array_column($cards, 'suit'));
    return count($suitsInHand) == 1 && count(array_diff($suitsInHand, $suits)) == 0;
}

// フルハウスの判定
function fullHouse($cards, $suits) {
    $count = array_count_values(array_column($cards, 'number'));
    return in_array(3, $count) && in_array(2, $count);
}

// フォーカードの判定
function fourCard($cards, $suits) {
    $count = array_count_values(array_column($cards, 'number'));
    return in_array(4, $count);
}

// ストレートフラッシュの判定
function straightFlush($cards, $suits) {
    return straight($cards, $suits) && isFlush($cards, $suits);
}

// ロイヤルストレートフラッシュの判定
function royalStraightFlush($cards, $suits) {
    $royal_numbers = [1, 10, 11, 12, 13];
    $numbers = array_column($cards, 'number');
    sort($numbers);
    return $numbers == $royal_numbers && isFlush($cards, $suits);
}

// 関数「judge」を呼び出して結果を表示する
echo "手札は\n";
foreach ($cards as $card) {
    echo "{$card['suit']}{$card['number']} ";
}
echo "\n";
echo judge($cards, $suits);

?>

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
var_dumpで出力してみましたが原因がよくわかりませんでした。

0

2Answer

PHP ポーカーって、同じ質問されている方がいるんですけど、同じ学校の宿題か何かですか?

役判定のロジック

それを考えるのが本課題の主目的のはずです。
他人任せにしようなど言語道断。そんなので学校卒業して、何になりたいのですか?なれると思っているのですか?

エンジニアとして不適切な発言でした。
大変申し訳ございませんでした。

1Like

Comments

  1. @RyotaOsawa

    Questioner

    そうですね。
    自分の考えが甘かったです。
    ご指摘ありがとうございます。

var_dumpで出力してみましたが原因がよくわかりませんでした。

どのような出力をしたのでしょうか?
目的を持って適切にvar_dumpを使用しないと、結果をただ眺めるだけになってしまいます。
var_dumpを適切に使用することで、処理の結果や処理の流れを確認することができます。

役判定のロジックの書き方

まず日本語でどのように判定するのか整理して考える必要があります。
コンピュータにやらせたい事が漠然としていては、命令(プログラミング)することはできません。同時に質問の内容も大づかみになってしまいますから、質問者がどのような思考・理解をしていてどこで躓いているのか把握できず、回答も難しくなります。

ポーカーの処理は「それぞれの役の判定」と「役判定の組み合わせ」になります。
まずは「それぞれの役の判定」に取り組みましょう。考えられる手札のパターンと、それに対する判定結果を整理します。そのうえで、判定処理の中身を考えていきましょう。
処理の中身は手順をリスト化したり、フローチャートにしてみるのも良いと思います。

1Like

Comments

  1. @RyotaOsawa

    Questioner

    回答ありがとうございます。
    考え方を変えたら少し分かった気がします。

Your answer might help someone💌