igusuke
@igusuke (すけ イグ)

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!

ポーカーの訳判定プログラムについての質問

現在僕はDXライブラリでポーカーゲームを作っています。

ランダムで画像を表示し、プレイヤーの手札の交換までは何とかなりました。(ランダム関数が重複ありなのは認知していますが今のところスルーでお願いします。)
最後に重要な勝敗判定なのですがこれがどのように書けばいいのかわかりません。
いまの空想では場に出ているカード画像の番号、記号から「ワンペア、ツーペア、スリーカード、フルハウス、フォーカード、ストレート、フラッシュ、ロイヤルストレートフラッシュ」の役を見出したいのです。
どのようにすればいいですか?
以下にコードを添付しておきます。

該当するソースコード

#include "DxLib.h"

int Key[256]; 


int gpUpdateKey() {
    char tmpKey[256]; 
    GetHitKeyStateAll(tmpKey); 
    for (int i = 0; i < 256; i++) {
        if (tmpKey[i] != 0) { 
            Key[i]++;     
        }
        else {              
            Key[i] = 0;   
        }
    }
    return 0;
}

int card_Graphic[52]; 

void load() {
    card_Graphic[0] = LoadGraph("Card\\A-1.png");
    card_Graphic[1] = LoadGraph("Card\\A-2.png");
    card_Graphic[2] = LoadGraph("Card\\A-3.png");
    card_Graphic[3] = LoadGraph("Card\\A-4.png");
    card_Graphic[4] = LoadGraph("Card\\A-5.png");
    card_Graphic[5] = LoadGraph("Card\\A-6.png");
    card_Graphic[6] = LoadGraph("Card\\A-7.png");
    card_Graphic[7] = LoadGraph("Card\\A-8.png");
    card_Graphic[8] = LoadGraph("Card\\A-9.png");
    card_Graphic[9] = LoadGraph("Card\\A-10.png");
    card_Graphic[10] = LoadGraph("Card\\A-11.png");
    card_Graphic[11] = LoadGraph("Card\\A-12.png");
    card_Graphic[12] = LoadGraph("Card\\A-13.png");
    card_Graphic[13] = LoadGraph("Card\\B-1.png");
    card_Graphic[14] = LoadGraph("Card\\B-2.png");
    card_Graphic[15] = LoadGraph("Card\\B-3.png");
    card_Graphic[16] = LoadGraph("Card\\B-4.png");
    card_Graphic[17] = LoadGraph("Card\\B-5.png");
    card_Graphic[18] = LoadGraph("Card\\B-6.png");
    card_Graphic[19] = LoadGraph("Card\\B-7.png");
    card_Graphic[20] = LoadGraph("Card\\B-8.png");
    card_Graphic[21] = LoadGraph("Card\\B-9.png");
    card_Graphic[22] = LoadGraph("Card\\B-10.png");
    card_Graphic[23] = LoadGraph("Card\\B-11.png");
    card_Graphic[24] = LoadGraph("Card\\B-12.png");
    card_Graphic[25] = LoadGraph("Card\\B-13.png");
    card_Graphic[26] = LoadGraph("Card\\C-1.png");
    card_Graphic[27] = LoadGraph("Card\\C-2.png");
    card_Graphic[28] = LoadGraph("Card\\C-3.png");
    card_Graphic[29] = LoadGraph("Card\\C-4.png");
    card_Graphic[30] = LoadGraph("Card\\C-5.png");
    card_Graphic[31] = LoadGraph("Card\\C-6.png");
    card_Graphic[32] = LoadGraph("Card\\C-7.png");
    card_Graphic[33] = LoadGraph("Card\\C-8.png");
    card_Graphic[34] = LoadGraph("Card\\C-9.png");
    card_Graphic[35] = LoadGraph("Card\\C-10.png");
    card_Graphic[36] = LoadGraph("Card\\C-11.png");
    card_Graphic[37] = LoadGraph("Card\\C-12.png");
    card_Graphic[38] = LoadGraph("Card\\C-13.png");
    card_Graphic[39] = LoadGraph("Card\\D-1.png");
    card_Graphic[40] = LoadGraph("Card\\D-2.png");
    card_Graphic[41] = LoadGraph("Card\\D-3.png");
    card_Graphic[42] = LoadGraph("Card\\D-4.png");
    card_Graphic[43] = LoadGraph("Card\\D-5.png");
    card_Graphic[44] = LoadGraph("Card\\D-6.png");
    card_Graphic[45] = LoadGraph("Card\\D-7.png");
    card_Graphic[46] = LoadGraph("Card\\D-8.png");
    card_Graphic[47] = LoadGraph("Card\\D-9.png");
    card_Graphic[48] = LoadGraph("Card\\D-10.png");
    card_Graphic[49] = LoadGraph("Card\\D-11.png");
    card_Graphic[50] = LoadGraph("Card\\D-12.png");
    card_Graphic[51] = LoadGraph("Card\\D-13.png");

}






int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
    ChangeWindowMode(TRUE), DxLib_Init();




    int haikei, mozi1, mozi2, ura;
    mozi1 = CreateFontToHandle("MS ゴシック", 50, 9, DX_FONTTYPE_NORMAL);
    mozi2 = CreateFontToHandle("MS ゴシック", 24, 6, DX_FONTTYPE_NORMAL);
    haikei = LoadGraph("haikei.jpg");
    ura = LoadGraph("Card\\ura.png");


    DrawRotaGraph(320, 240, 0.5, 0.0, haikei, TRUE);
    DrawFormatString(25, 220, GetColor(255, 255, 255), "1P");
    DrawFormatString(25, 370, GetColor(255, 255, 255), "2P");

    while (1) {

        ProcessMessage();
        DrawStringToHandle(100, 65, "ポーカーゲーム開始。", GetColor(255, 255, 255), mozi1);
        DrawStringToHandle(250, 117, "Enterで次へ", GetColor(255, 255, 255), mozi2);
        if (CheckHitKey(KEY_INPUT_RETURN) == 1) {
            break;


        }
    }

    ClearDrawScreen();



    DrawRotaGraph(320, 240, 0.5, 0.0, haikei, TRUE);
    DrawFormatString(25, 220, GetColor(255, 255, 255), "1P");
    DrawFormatString(25, 370, GetColor(255, 255, 255), "2P"); 
    DrawStringToHandle(250, 117, "Enterで2Pへ", GetColor(255, 255, 255), mozi2);
    DrawStringToHandle(60, 75, "[1P]交換するカードの番号を選択してください", GetColor(255, 255, 255), mozi2);
    DrawFormatString(105, 287, GetColor(255, 255, 255), "1");
    DrawFormatString(215, 287, GetColor(255, 255, 255), "2");
    DrawFormatString(325, 287, GetColor(255, 255, 255), "3");
    DrawFormatString(435, 287, GetColor(255, 255, 255), "4");
    DrawFormatString(545, 287, GetColor(255, 255, 255), "5");


        load();

        DrawRotaGraph(110, 220, 0.125, 0.0 , card_Graphic[GetRand(51)] , TRUE);
        DrawRotaGraph(220, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(330, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(440, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(550, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);


        DrawRotaGraph(110, 370, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(220, 370, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(330, 370, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(440, 370, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(550, 370, 0.125, 0.0, ura, TRUE);

        int flag1 = 0;
        int flag2 = 0;
        int flag3 = 0;
        int flag4 = 0;
        int flag5 = 0;


        while (1) {

            ProcessMessage();
            gpUpdateKey();

            if ((Key[KEY_INPUT_1] == 1) && !flag1) {
                DrawRotaGraph(110, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag1 = 1;

            }
            if ((Key[KEY_INPUT_2] == 1) && !flag2) {
                DrawRotaGraph(220, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag2 = 1;

            }
            if ((Key[KEY_INPUT_3] == 1) && !flag3) {
                DrawRotaGraph(330, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag3 = 1;

            }
            if ((Key[KEY_INPUT_4] == 1) && !flag4) {
                DrawRotaGraph(440, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag4 = 1;

            }
            if ((Key[KEY_INPUT_5] == 1) && !flag5) {
                DrawRotaGraph(550, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag5 = 1;

            }
            if (Key[KEY_INPUT_RETURN] == 1) {
                break;
            }
        }

        ClearDrawScreen();
        DrawRotaGraph(320, 240, 0.5, 0.0, haikei, TRUE);
        DrawFormatString(25, 220, GetColor(255, 255, 255), "1P");
        DrawFormatString(25, 370, GetColor(255, 255, 255), "2P");


        DrawStringToHandle(250, 117, "Enterで次へ", GetColor(255, 255, 255), mozi2);
        DrawStringToHandle(60, 75, "[2P]交換するカードの番号を選択してください", GetColor(255, 255, 255), mozi2);
        DrawFormatString(105, 287, GetColor(255, 255, 255), "1");
        DrawFormatString(215, 287, GetColor(255, 255, 255), "2");
        DrawFormatString(325, 287, GetColor(255, 255, 255), "3");
        DrawFormatString(435, 287, GetColor(255, 255, 255), "4");
        DrawFormatString(545, 287, GetColor(255, 255, 255), "5");

        DrawRotaGraph(110, 220, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(220, 220, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(330, 220, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(440, 220, 0.125, 0.0, ura, TRUE);
        DrawRotaGraph(550, 220, 0.125, 0.0, ura, TRUE);

        load();

        DrawRotaGraph(110, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(220, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(330, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(440, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
        DrawRotaGraph(550, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);

        int flag6 = 0;
        int flag7 = 0;
        int flag8 = 0;
        int flag9 = 0;
        int flag0 = 0;


        while (1) {

            ProcessMessage();
            gpUpdateKey();

            if ((Key[KEY_INPUT_1] == 1) && !flag6) {
                DrawRotaGraph(110, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag6 = 1;

            }
            if ((Key[KEY_INPUT_2] == 1) && !flag7) {
                DrawRotaGraph(220, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag7 = 1;

            }
            if ((Key[KEY_INPUT_3] == 1) && !flag8) {
                DrawRotaGraph(330, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag8 = 1;

            }
            if ((Key[KEY_INPUT_4] == 1) && !flag9) {
                DrawRotaGraph(440, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag9 = 1;

            }
            if ((Key[KEY_INPUT_5] == 1) && !flag0) {
                DrawRotaGraph(550, 370, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
                flag0 = 1;

            }
            if (Key[KEY_INPUT_RETURN] == 1) {
                break;
            }
        }








        WaitKey();

    DxLib_End();                

    return 0;               
}

0

2Answer

ご質問に対して、直接的な回答でないことをお許しください。

カードを表示するときに、発生させた乱数から直接描画していますよね?
そのため、発生させた乱数がいくつだったのか、記録が残っていません。
画面にカードは表示されていますが、そのカードがいくつだったのかをプログラムが知るためには、画面から画素を読み取る必要がありそうです。
発生させた乱数(カード番号)を何処かに保存しておいて、その数値のセットから役を検証するようにすると良いのではないでしょうか。


私が作るのでしたら、山札(ストック)、場札(捨て札)、手札(×2)を、配列やリストに保持するなどして、表示に関係なく論理的にゲームが進められるようにすると思います。

例えば、配列で考えてみましょう。
カードの種類による番号を決めておきます。
数字は1~13、種類はスペードが100、ハートが200、クラブが300、ダイヤが400としましょう。

種類 番号
スペード 101 ~ 113
ハート 201 ~ 213
クラブ 301 ~ 313
ダイヤ 401 ~ 413

ゲーム開始直後は、52枚全ての札が山札にあります。
場札や手札は何もありません。
山札はシャッフルされていません。

#define MAX_CARD (52)
#define MAX_HAND (5)
int yamahuda[MAX_CARD] = { 101, 102, 103, 104, 105, ..., 411, 412, 413 };
int bahuda[MAX_CARD] = { 0, ..., 0 };
int p1tehuda[MAX_HAND] = { 0, 0, 0, 0, 0 };
int p2tehuda[MAX_HAND] = { 0, 0, 0, 0, 0 };

…こんな感じでしょうか。
以下のような形でコンソールに表示できるようにしておきます。

山札: 101, 102, 103, 104, 105, ..., 411, 412, 413
場札: 0, ..., 0
手札1: 0, 0, 0, 0, 0
手札2: 0, 0, 0, 0, 0

山札をシャッフルします。

山札: 101, 105, 210, 204, 213, ..., 212, 312, 106
場札: 0, ..., 0
手札1: 0, 0, 0, 0, 0
手札2: 0, 0, 0, 0, 0

手札が配られると、その分だけ山札は減ります。
カードがなくなったところは0にしました。

山札: 0, 0, 0, 0, 0, ..., 212, 312, 106
場札: 0, ..., 0
手札1: 101, 210, 213, 304, 404
手札2: 105, 204, 307, 407, 412

手札を交換すると、山札が減り、手札が入れ替わって、場札が増えます。

山札: 0, 0, 0, 0, 0, ..., 212, 312, 106
場札: 101, 210, 213, 304, 404, ..., 0
手札1: 102, 202, 302, 402, 113
手札2: 105, 204, 307, 407, 412


私が作るのでしたら、まず、このような形で、論理的なゲームを作ってしまいます。
この場合、役の判定は、手札の配列をソートした上で、1,2桁(数)と3桁(種類)を、「5枚とも同じ種類で」とか、「数が1ずつ増えて」などと、チェックしていく感じでしょうか。

最後に、「これらの配列が変化する度に、画面にカードを表示する処理」を組み合わせるとゲームが完成します。

※この説明で用いた配列は、説明を容易にするためのもので、実際の開発に適したものではありません。
※ポーカーを知らないので、ルール的に変なことをしていたらごめんなさい。

4Like

自分だったら…

手札を引数にして役オブジェクト(役名、強さ)を返すメソッドを作る。
役の強い順に判定し、一致したらその役オブジェクトを返す。
強さで比較して勝敗を決める。

同役だったとき用の勝敗判定メソッドも作る。
ただ同役の勝敗判定はググったところ面倒くさそうだった。

本題とは関係ないですけど
loadメソッドとか、

DrawRotaGraph(110, 220, 0.125, 0.0, card_Graphic[GetRand(51)] ,TRUE);
DrawRotaGraph(220, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
DrawRotaGraph(330, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
DrawRotaGraph(440, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);
DrawRotaGraph(550, 220, 0.125, 0.0, card_Graphic[GetRand(51)], TRUE);

みたいな箇所はfor分で書いたほうが見やすいと思います。
flag0~flag9も配列で表したほうがよいのではないでしょうか。

(追記)
役クラスは別に作らなくてもいいです。役名をキー、強さを値にした辞書型でも表現できるので

1Like

Comments

  1. @igusuke

    Questioner

    辞書型と数値の強さの定義を合わせて勝敗判定することってできますかね?すみませんプログラミング始めたてでうまく言えてないと思いますが…
  2. 辞書型の下りは頭の中でこう考えていました。(C#の構文にあってなかったらすみません。)

    var 役の強さ = new Dictionary<string, string>() {
     {"ブタ", 0},
     {"ワンペア", 1},
     {"ツーペア", 2},
     ・・・
    };

    string player1役名 = getHandName(player1.手札);
    string player2役名 = getHandName(player2.手札);

    if (役の強さ[player1役名] > 役の強さ[player2役名]) {
     // player1の勝ち
    }
    else if (役の強さ[player1役名] < 役の強さ[player2役名]) {
     // player2の勝ち
    }
    else {
     // 同役の勝敗判定をする
    }
  3. @igusuke

    Questioner

    DXライブラリの使用言語はC++なんでC#のvarは多分使えないと思います…C#使ったことないのでわからないのですが…
  4. やらかした…
    すみません。適当に読み替えてください。

Your answer might help someone💌