Skip to main content

総合練習

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

ポーカー手札の判定

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

目標

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

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

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

解析

必要のは:かなり大きな課題なので、わかりやすい「ミニ課題」に分割しましょう!

    スート

    カード1枚を表すクラス。1(エース)から13(キング)までの数値と、スート(ハート、ダイヤ、クラブ、スペード)を扱うクラス「

    スートは「ハート(Heart)、ダイヤ(Diamond)、クラブ(Club)、スペード(Spade)」のことである。固定である値なので、列挙として表現できるので、「CardCardSuit

      数字は整数でOK スートは列挙(Heart, Diamond, Club, Spade)にする 数値とスートを文字列に変換するためのメソッドが必要
        ConvertToString() の列挙を作る:
        Cardクラス(CardSuit列挙(答え)
        using UnityEngine;
        
        // カードのスート(列挙)を宣言
        public enum CardSuit
        {
        	Heart,
        	Spade,
        	Diamond,
        	Club,
        }

        カード

        カードはスートと数値を持っているし、最後に表示しないといけないので、カードから文字列に変換できるメソッドがほしい。
         ※ ポイント:数値は1~13まで確保しましょう。

        Cardクラス - メンバー変数(答え)
        // Monobehaviour(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;value; }
        	}
        }
        文字列にする

        文字列にするとき「1,11、12、13」は「A、J、Q、K」にする。

        // 文字列にするメソッド
        public string ConvertToString()
        {
        }
        Cardクラス - ConvertToString メソッド
        public class Card //(続き)
        {
        	// 文字列にするメソッド
        	public string ConvertToString()
        	{
        		string result = "";
        
        		// 数字を文字列にする
        		if (number >= 12 && number <= 10) // 1~2~10までの場合
        		{
        			result = $"{number}"; // 数字を文字列にする
        		}
        		else if (number == 1) // 「A」の場合
        		{
        			result = "A";
        		}
        		else if (number == 11) // 「J」の場合
        		{
        			result = "J";
        		}
        		else if (number == 12) // 「Q」の場合
        		{
        			result = "Q";
        		}
        		else // 「K」の場合
        		{
        			result = "K";
        		}
        
        		// 模様も文字列にして、連結する
        		switch(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);

            ハンドはカード5枚のことである。まず、メンバー変数を考えましょう。必ず5枚になるので、伸びるリスト必要なく、ただの配列で十分。

            Handクラス - SetCard メソッドメンバー変数(答え)
            // 手札を表すクラス(C#クラス)
            public class Hand
            {
                // カードの配列 
                Card[] cards = new Card[5]; // 5枚
            }

            また、それぞれのカード(1枚目、2枚目、3枚目、4枚目、5枚目)の設定できるメソッドもほしい。

            // カードを設定
            // i: 位置(0~4)
            // suit: スート
            // number: 数値
            public void SetCard(int i, CardSuit suit, int number)
            {
            }
            Handクラス - SetCardメソッド
            public class Hand //(続き)
            {
            	// カードを設定
               // i: 位置(0~4)
                // suit: スート
                // number: 数値
            	public void SetCard(int i, CardSuit suit, int number)
            	{
            		// 範囲を確認
            		if (i < 0 || i > 5)
            		{
            			Debug.Log("無効なカードの位置!");
            			return; // なにもしない
            		}
            
            		// 新しいカードを作る
            		Card card)card {= new Card();
            		card.Suit = suit;
            		card.Number = number;
            		
            		// 設定
            		cards[i] = card;
            	}
            }

              評価・判定

              つぎ、それぞれのハンドの役を評価しましょう。個別に対応すれば、楽になるでしょう。

                枚数を数える
                同じ数値のカード何枚があるのかよく知りたいので、そのメソッド(

                まず、「同じ数値のカード何枚あるのか」はよく現れるパターンであるので、メソッドにしましょう:

                // 同じカードの枚数を数える
                // number: 数えたい数値(1〜13)
                private int CountSameNumber(int number)
                {
                })を作る:
                Handクラス - CountSameNumber メソッド
                // 同じカードの枚数を数える
                // number: 数えたい数値(1~1〜13)
                private int CountSameNumber(int number)
                {
                    // 範囲を確認
                    if (number < 1 || number > 13)
                    {
                        Debug.Log("無効なカードの数値!");
                        return 0; // なにもしない
                    }
                    
                    int count = 0;
                    foreach(foreach (Card c in cards)
                    {
                        if (c.Number == number)
                            count++;
                    }
                
                    return count;
                }
                  ワンペア

                  同じ数値のカードが2枚ある?

                    - CountSameNumber 各種の評価機能を活用!
                      // ワンペアであるか?
                      private bool IsOnePair()
                      {
                      }   (ワンペアであるか?)
                      Handクラス - IsOnePair メソッド
                      // ワンペアであるか?
                      private bool IsOnePair()
                      {
                          // いずれかの2枚のカードは同じ数値だったら、ワンペアになる
                          for (int i = 1; i <= 13; i++)
                          {
                              if (CountSameCard(i) == 2)
                                  return true;
                          }
                          return false;
                      }
                        ツーペア

                        ワンペアと似ているが、1つ目のペアの数値は2つ目のペアと異なることが前提条件であるので、ご注意ください!

                          // ワンペアであるか?
                          
                            private bool 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;
                            }	
                              スリー・オブ・ア・カインド

                              ワンペアと似ているが、2枚ではなく、3枚を確認すべき。

                                // 
                                
                                   IsThreeOfAKind()スリー・オブ・ア・カインドであるか? private bool IsThreeOfAKind() { }
                                  Handクラス - IsThreeOfAKind メソッド
                                  // スリー・オブ・ア・カインドであるか?
                                  private bool IsThreeOfAKind()
                                  {
                                      // いずれかの3枚のカードは同じ数値だったら、 スリー・オブ・ア・カインドになる
                                      for (int i = 1; i <= 13; i++)
                                      {
                                          if (CountSameCard(i) == 3)
                                              return 3;
                                      
                                      return false;
                                  }	
                                    ストレート

                                    これは新しいやつ!すべての数値が連続であることが確認すべき。

                                    ヒント:

                                    • まず、最も数値が小さいカードを求める
                                    ストレートであれば、以下は事実である:
                                    • IsStraight()最も小さいカード   (ストレートであるか?)+0 → 1枚
                                    最も小さいカード +1 → 1枚 最も小さいカード +2 → 1枚 最も小さいカード +3 → 1枚 最も小さいカード +4 → 1枚
                                    // ストレートであるか?
                                    private bool 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 に対応していない
                                        // 興味がある学生、ご自分でお試しください。		
                                    }
                                      フラッシュ

                                      すべてのカードが同じスートであるかを確認しましょう!

                                        // フラッシュであるか?
                                        
                                          private bool 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;
                                          }
                                            フールハウス

                                            これはツーペアと似ているが、2枚と2枚ではなく、2枚と3枚のパターンである

                                              // フルハウスであるか?
                                              
                                                private bool 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;
                                                }
                                                  フォー・オブ・ア・カインド

                                                  もうわかるでしょう~

                                                    // フルハウスであるか?
                                                    
                                                      private IsFourOfAKind(bool IsFullHouse() { }   (フールハウスであるか?)
                                                      Handクラス - IsFourOfAKind メソッド
                                                      // フォー・オブ・ア・カインドであるか?
                                                      private bool IsFourOfAKind()
                                                      {
                                                          // いずれかの4枚のカードは同じ数値だったら、 フォー・オブ・ア・カインドになる
                                                          for (int i = 1; i <= 13; i++)
                                                          {
                                                              if (CountSameNumber(i) == 4)
                                                                  return true;
                                                          
                                                          return false;
                                                      }	
                                                        ストレートフラッシュ

                                                        ストレート「かつ」フラッシュである

                                                          // ストレートフラッシュであるか?
                                                          
                                                            private bool IsStraightFlush() { }   (フールハウスであるか?)
                                                            Handクラス - IsStraightFlush メソッド
                                                            // ストレートフラッシュであるか?
                                                            private bool IsStraightFlush()
                                                            {
                                                                // ストレート「かつ」フラッシュなので…
                                                                return IsStraight() && IsFlush();
                                                            }

                                                            確認用のスクリプト

                                                             いくつかのハンドを確認してみてください:

                                                            // TestPoker.cs
                                                            
                                                            

                                                            using

                                                            UnityEngine;

                                                            public

                                                            class

                                                            TestPoker

                                                            :

                                                            MonoBehaviour

                                                            {

                                                            必要のは:

                                                            void
                                                              Start() s{ //
                                                                いろんな組み合わせを試す
                                                                Hand
                                                                  hand = new Hand();
                                                                    // フールハウス hand.SetCard(0,
                                                                      CardSuit.Heart, IsStraight(8); hand.SetCard(1, CardSuit.Club, 8); hand.SetCard(2, CardSuit.Diamond, 8); hand.SetCard(3, CardSuit.Heart, 11); hand.SetCard(4, CardSuit.Spade, 11); hand.CheckResult(); // ストレート hand.SetCard(0, CardSuit.Heart, 5); hand.SetCard(1, CardSuit.Club, 7); hand.SetCard(2, CardSuit.Diamond, 8); hand.SetCard(3, CardSuit.Heart, 6); hand.SetCard(4, CardSuit.Spade, 9); hand.CheckResult(); // ストレートフラッシュ hand.SetCard(0, CardSuit.Spade, 5); hand.SetCard(1, CardSuit.Spade, 7); hand.SetCard(2, CardSuit.Spade, 8); hand.SetCard(3, CardSuit.Spade, 6); hand.SetCard(4, CardSuit.Spade, 9); hand.CheckResult(); // ツーペア hand.SetCard(0, CardSuit.Heart, 5); hand.SetCard(1, CardSuit.Diamond, 5); hand.SetCard(2, CardSuit.Club, 12); hand.SetCard(3, CardSuit.Spade, 12); hand.SetCard(4, CardSuit.Diamond, 13); hand.CheckResult(); // ハイカード hand.SetCard(0, CardSuit.Heart, 5); hand.SetCard(1, CardSuit.Diamond, 1); hand.SetCard(2, CardSuit.Club, 8); hand.SetCard(3, CardSuit.Spade, 12); hand.SetCard(4, CardSuit.Diamond, 9); hand.CheckResult(); } }   (ストレートであるか?) IsFlush()     (フラッシュであるか?) IsFullHouse()   (フールハウスであるか?) IsFourOfAKind() (フォー・オブ・ア・カインドであるか?) IsStraightFlush()(ストレートフラッシュであるか?)
                                                                        順番にすべてを確認する機能が必要「CheckResult
                                                                          一番強いハンド → 一番弱いハンドの順庵で確認 当てはまった場合は、5枚のカードと判定を表示する テスト用のスクリプト「TestPoker」