Skip to main content

総合練習

変数、条件分岐、配列(またはリスト)、列挙、メソッドとクラスを使い、以下のスクリプト作りましょう

ポーカー手札の判定

参考:ポーカー・ハンドの一覧

目標

手札にある5枚のカードを確認し、評価し、Debug.Logで判定を表示。

例:A♥ A♦ 10♣ 7♦ 3♠ - ワンペア

を表示するのは目標である

解析

必要のは:

  • カード1枚を表すクラス。1(エース)から13(キング)までの数値と、スート(ハート、ダイヤ、クラブ、スペード)を扱うクラス「Card
    • 数字は整数でOK
    • スートは列挙(Heart, Diamond, Club, Spade)にする
    • 数値とスートを文字列に変換するためのメソッドが必要
      • ConvertToString()
Cardクラス(答え)
using UnityEngine;

// カードのスート(列挙)を宣言
public enum CardSuit
{
	Heart,
	Spade,
	Diamond,
	Club,
}

// Monobehaviour(Unityのクラス)ではないので
public class Card 
{
	// カードの数字
	private int number;

	// カードのスート
	private CardSuit suit;

	// カードの数字
	public int Number 
	{
		get { return number; }
		set 
		{
			// Mathf.Clampは最小値と最大値の制限をかける
			number = Mathf.Clamp(value, 1, 13);
		}
	}

	// カードのスート
	public CardSuit Suit
	{
		get { return suit; }
		set { suit = Suit; }
	}

	// 文字列にするメソッド
	public string ConvertToString()
	{
		string result = "";

		// 数字を文字列にする
		if (number >= 1 && number <= 10)  // 1~10までの場合
		{
			result = $"{number}";        // 数字を文字列にする
		}

		else if (number == 11)	// 「J」の場合
		{
			result = "J";
		}

		else if (number == 12)  // 「Q」の場合
		{
			result = "Q";
		}

		else					// 「K」の場合
		{
			result = "K";
		}

		// 模様も文字列にして、連結する
		switch(suit) // "suit"で切り替える
		{
			case CardSuit.Heart:
				result += "♥";  // ハート
				break;
			case CardSuit.Diamond:
				result += "♦"; // ダイヤ
				break;
			case CardSuit.Club:
				result += "♣"; // クラブ
				break;
			case CardSuit.Spade:
				result += "♠"; // スペード
				break;
		}

		return result;
	}
}
  • 5枚のカード表すハンド「Hand」クラス
    • 5枚を設定する方法が必要:SetCard(int i, Card card);
Handクラス - SetCard メソッド
// 手札を表すクラス(C#クラス)
public class Hand
{
    // カードの配列 
    Card[] cards = new Card[5]; // 5枚
    
    // カードを設定
    public void SetCard(int i, Card card)
    {
        cards[i] = card;
    }
}
    • 同じ数値のカード何枚があるのかよく知りたいので、そのメソッド(CountSameNumber(int number))を作る:
Handクラス - CountSameNumber メソッド
// 同じカードの枚数を数える
// number: 数えたい数値(1~13)
private int CountSameNumber(int number)
{
    int count = 0;
    foreach(Card c in cards)
    {
        if (c.Number == number)
            count++;
    }
    return count;
}
    •  各種の評価機能
      • IsOnePair()   (ワンペアであるか?)
Handクラス - IsOnePair メソッド
// ワンペアであるか?
private bool IsOnePair()
{
    // いずれかの2枚のカードは同じ数値だったら、ワンペアになる
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameCard(i) == 2)
            return true;
    }
    return false;
}
      • IsTwoPair()   (ツーペアであるか?)
Handクラス - IsTwoPair メソッド
// ツーペアであるか?
private bool IsTwoPair()
{
    // ワンペアと似ているが、2つのペアは異なるカードじゃないとだめ
    int match = 0;  // 1つ目のペアの数値
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameCard(i) == 2)
            match = i;
    }
    
    // なにも一致しなかった
    if (match == 0)
        return false;
    
    // もう一つのペアがないか確認する
    for (int i = 1; i <= 13; i++)
    {
        // 2枚がある「かつ」前のペアと異なる
        if (CountSameCard(i) == 2 && i != match)
            return true;
    }
    
    return false;
}	
      •  IsThreeOfAKind()(スリー・オブ・ア・カインドであるか?)
Handクラス - IsThreeOfAKind メソッド
// スリー・オブ・ア・カインドであるか?
private bool IsThreeOfAKind()
{
    // いずれかの3枚のカードは同じ数値だったら、 スリー・オブ・ア・カインドになる
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameCard(i) == 3)
            return 3;
    
    return false;
}	
      • IsStraight()   (ストレートであるか?)
Handクラス - IsStraight メソッド
// ストレートであるか?
private bool IsStraight()
{
    // 連続になっているのかを確認が必要
    // 例えば: 8-9-10-J(11)-Q(12)
    
    // まず、最低のカードを求めましょう
    int smallCard = 14; // Kよりも高いから始まる
    foreach (Card c in cards)
    {
        if (c.Number < smallCard)
            smallCard = c.Number; // 最低カードを更新
    }
    
    // では、5枚も連続であれば、各カード +1 は
    // 必ず1枚ずつがあるはず
    for (int i = smallCard; i < smallCard + 5; i++)
    {
        // 1つだけ!
        if (CountSameNumber(i) != 1)
            return false;
    }
    
    // 順番に1枚ずつがあった!
    return true;

    // メモ:A-K-Q-J-10 に対応していない
    // 興味がある学生、ご自分でお試しください。		
}
      • IsFlush()     (フラッシュであるか?)
Handクラス - IsFlush メソッド
// フラッシュであるか?
private bool IsFlush()
{
    // すべて同じスートでであればOK
    CardSuit suit = cards[0].Suit;
    
    // 残りのを確認
    foreach(Card c in cards)
    {
        if (c.Suit != suit)
            return false;
    }
    
    return true;
}
      • IsFullHouse()   (フールハウスであるか?)
Handクラス - IsFullHouse メソッド
// フルハウスであるか?
private bool IsFullHouse()
{
    // ツーペアと似ているが、枚数は2枚と3枚になる
    int match = 0;  // 1つ目のペアの数値
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameNumber(i) == 2)
            match = i;
    }
    
    // なにも一致しなかった
    if (match == 0)
        return false;
    
    // 残りの3枚を数える
    for (int i = 1; i <= 13; i++)
    {
        // 3枚がある「かつ」前のペアと異なる
        if (CountSameNumber(i) == 3 && i != match)
            return true;
    }
    
    return false;
}
      • IsFourOfAKind()   (フールハウスであるか?)
Handクラス - IsFourOfAKind メソッド
// フォー・オブ・ア・カインドであるか?
private bool IsFourOfAKind()
{
    // いずれかの4枚のカードは同じ数値だったら、 フォー・オブ・ア・カインドになる
    for (int i = 1; i <= 13; i++)
    {
        if (CountSameNumber(i) == 4)
            return true;
    
    return false;
}	
      • IsStraightFlush()   (フールハウスであるか?)
Handクラス - IsStraightFlush メソッド
// ストレートフラッシュであるか?
private bool IsStraightFlush()
{
    // ストレート「かつ」フラッシュなので…
    return IsStraight() && IsFlush();
}

 

 

 

 

 

 

必要のは:


      •  
        •  
          • IsStraight()   (ストレートであるか?)
          • IsFlush()     (フラッシュであるか?)
          • IsFullHouse()   (フールハウスであるか?)
          • IsFourOfAKind() (フォー・オブ・ア・カインドであるか?)
          • IsStraightFlush()(ストレートフラッシュであるか?)
          • 順番にすべてを確認する機能が必要「CheckResult
            • 一番強いハンド → 一番弱いハンドの順庵で確認
            • 当てはまった場合は、5枚のカードと判定を表示する
  • テスト用のスクリプト「TestPoker」