challenge ポーカーの役判定

引数に手札を与えると、ポーカーの役を表示するプログラムを作ってください。

条件:

  • スートはS,D,H,C、ランクはA,2~9,T,J,Q,Kのそれぞれ一文字で表します。
  • 手札は S2D5H3CQS9 のように10文字で指定されます。特にソートはされていません。
  • 手札にジョーカーは含まれません。
  • ストレートで取りうるランクの種類はA2345, 23456 ... 9TJQK, TJQKAの10種類で、JQKA2のようにK-A-2をまたぐものはストレートではありません。

実行例:

% ./poker SQSJSASKST
Royal flush

% ./poker D9D7D6D5D8
Straight flush

% ./poker C2D2S2H3H2
Four of a kind

% ./poker C2D3S2H3H2
Full house

% ./poker S9S4S8STSJ
Flush

% ./poker C4H7D5S6H3
Straight

% ./poker S6H6C5DQC6
Three of a kind

% ./poker S6HQC5DQC6
Two pair

% ./poker S6H4C5DQC6
One pair

% ./poker SJSQSKSAC2
No pair

お題にしようと思っていたのに間違えてしまいました。今から変更可能でしょうか?

(説明)
当初間違ってトピックに投稿していたので、このようなコメントを付けていたのですが、
このコメントに気づいた管理人さんにお題に移していただきました。
(最初の2つだけ投稿日時が早いのはそのためです)

Posted feedbacks - C#

一切コメント無しでも充分な可読性を目指しました。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
//http://ja.doukaku.org/121/ 投稿用
using System;
using System.Collections.Generic;

class Program {
    const string Ranks = "A23456789TJQKA";
    const string Suits = "SDHC";
    static void Main(string[] args) {
        if(IsRoyalStraightFlush(args[0])) Console.WriteLine("Royal straight flush");
        else if(IsStraightFlush(args[0])) Console.WriteLine("Straight flush");
        else if(Is4cards(args[0])) Console.WriteLine("Four of a kind");
        else if(IsFullHouse(args[0])) Console.WriteLine("Full house");
        else if(IsFlush(args[0])) Console.WriteLine("Flush");
        else if(IsStraight(args[0])) Console.WriteLine("Straight");
        else if(Is3Cards(args[0])) Console.WriteLine("Three of a kind");
        else if(Is2Pair(args[0])) Console.WriteLine("Two pair");
        else if(Is1Pair(args[0])) Console.WriteLine("One pair");
        else Console.WriteLine("No pair");
        Console.ReadLine();
    }

    static bool IsRoyalStraightFlush(string cards){
        if(IsFlush(cards) && IsStraight(cards)){
            for(int i = 2; i <= 9; i++) {//2~9までの数字が含まれていたらNG
                if(cards.IndexOf(i.ToString()) != -1) return false;
            }
            return true;
        }
        return false;
    }

    static bool IsStraightFlush(string cards) {
        return IsFlush(cards) && IsStraight(cards);
    }

    static bool Is4cards(string cards) {
        return IsAnyCards(cards, 4);
    }

    static bool IsFullHouse(string cards) {
        return Is3Cards(cards) && Is1Pair(cards);
    }

    static bool IsFlush(string cards) {
        foreach(char suit in Suits.ToCharArray()) {//あるスーツの文字を切り取って
            if(cards.Length - cards.Replace(suit.ToString(),"").Length == 5) return true;
            //5文字減ったら5枚全て同じスーツ
        }
        return false;
    }

    static bool IsStraight(string cards) {
        List<string> rankListInCards = new List<string>();//カードのランクのみ
        //ランク切り出し
        for(int i = 1; i <= 9; i = i + 2) {
            rankListInCards.Add(cards[i].ToString());
        }
        //並び替え
        rankListInCards.Sort(cardRankSort);
        //ソート済みカードリスト作成
        string sortedCards = "";
        foreach(string card in rankListInCards) {
            sortedCards += card;
        }
        //判定
        if(Ranks.Contains(sortedCards)) return true;
        if(sortedCards[0] == 'A') {//先頭がAなら
            //末尾に移してもう一度判定
            if(Ranks.Contains(sortedCards.Remove(0, 1).PadRight(5, 'A'))) return true;
        }
        return false;
    }

    static bool Is3Cards(string cards) {
        return IsAnyCards(cards, 3);
    }

    static bool Is2Pair(string cards) {
        foreach(char Rank in Ranks.ToCharArray()) {
            if(cards.Length - cards.Replace(Rank.ToString(), "").Length == 2) {//One pairだったら
                return Is1Pair(cards.Replace(Rank.ToString(),""));//One pairが2回でTwo pair
            }
        }
        return false;
    }

    static bool Is1Pair(string cards) {
        return IsAnyCards(cards, 2);
    }

    //あるカードがany枚含まれているかどうかを判定
    static bool IsAnyCards(string cards, int any) {
        foreach(char Rank in Ranks.ToCharArray()) {
            if(cards.Length - cards.Replace(Rank.ToString(), "").Length == any) return true;
        }
        return false;
    }

    static int cardRankSort(string x, string y) {
        return Ranks.IndexOf(x) - Ranks.IndexOf(y); 
    }
}

思ったより時間かかってしまいました
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;

namespace Poker
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 1)
                return;

            Poker poker = new Poker(args[0]);
            Console.WriteLine(poker.Judge());
        }
    }

    public class Poker
    {
        static string RANK = "A23456789TJQK";
        string cards;
        string ranks;

        public Poker(string card)
        {
            cards = card;
            ranks = SortRanks();
        }

        public string Judge()
        {
            bool isRoyalStraight = ranks == "ATJQK";
            bool isStraight = RANK.IndexOf(ranks) >= 0;
            bool isFlush = IsFlush();
            string sameRanks = GetSameRanks();

            if (isRoyalStraight && isFlush)
                return "Royal flush";
            else if (isStraight && isFlush)
                return "Straight flush";
            else if (isStraight)
                return "Straight";
            else if (isFlush)
                return "Flush";
            else if (sameRanks == "4")
                return "Four of a kind";
            else if (sameRanks == "23")
                return "Full house";
            else if (sameRanks == "3")
                return "Three of a kind";
            else if (sameRanks == "22")
                return "Two pair";
            else if(sameRanks == "2")
                return "One pair";
            else
                return "No pair";
        }

        private string GetSameRanks()
        {
            int[] rankArray = new int[13];
            string sameRanks = "";

            for (int i = 0; i < rankArray.Length; i++)
                rankArray[i] = 0;

            for (int i = 0; i < ranks.Length; i++) {
                switch (ranks[i]) {
                    case 'A':
                    rankArray[0]++;
                    break;
                    case 'T':
                    rankArray[9]++;
                    break;
                    case 'J':
                    rankArray[10]++;
                    break;
                    case 'Q':
                    rankArray[11]++;
                    break;
                    case 'K':
                    rankArray[12]++;
                    break;
                    default:
                    rankArray[ranks[i] - 48 - 1]++;
                    break;
                }
            }

            Array.Sort(rankArray);
            foreach (int n in rankArray) {
                if (n > 1)
                    sameRanks += n.ToString();
            }

            return sameRanks;
        }

        private bool IsFlush()
        {
            char suit = cards[0];
            for (int i = 2; i < cards.Length; i += 2) {
                if (cards[i] != suit)
                    return false;
            }

            return true;
        }

        private string SortRanks()
        {
            char[] rankBuff = new char[5];
            string sortedRank = "";

            for (int i = 0; i < rankBuff.Length; i++)
                rankBuff[i] = cards[i * 2 + 1];

            for (int i = 0; i < RANK.Length; i++) {
                char c = RANK[i];
                foreach (char c2 in rankBuff) {
                    if (c == c2)
                        sortedRank += c.ToString();
                }
            }

            return sortedRank;
        }
    }
}

ワイルドカード(WWで表す)に対応させてみました。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//http://ja.doukaku.org/121/ 投稿用
using System;
using System.Collections.Generic;

class Program {
    const string Ranks = "A23456789TJQKA";
    const string Suits = "SDHC";
    enum Hands {
        Five_of_a_kind = 10,
        Royal_straight_flush = 9,
        Straight_flush = 8,
        Four_of_a_kind = 7,
        Full_house = 6,
        Flush = 5,
        Straight = 4,
        Three_of_a_kind = 3,
        Two_pair = 2,
        One_pair = 1,
        No_pair = 0
    }

    static void Main(string[] args) {
        Hands hand = 0;
        foreach(char suit in Suits.ToCharArray()) {
            foreach(char rank in Ranks.Remove(0, 1).ToCharArray()) {
                string wildCard = suit.ToString() + rank.ToString();
                Hands tmpHand = GetHands(args[0].Replace("WW", wildCard));
                hand = tmpHand > hand ? tmpHand : hand;
            }
        }
        Console.WriteLine(hand);
        Console.ReadLine();
    }

    static Hands GetHands(string cards) {
        if(Is5cards(cards)) return Hands.Five_of_a_kind;
        else if(IsRoyalStraightFlush(cards)) return Hands.Royal_straight_flush;
        else if(IsStraightFlush(cards)) return Hands.Straight_flush;
        else if(Is4cards(cards)) return Hands.Five_of_a_kind;
        else if(IsFullHouse(cards)) return Hands.Full_house;
        else if(IsFlush(cards)) return Hands.Flush;
        else if(IsStraight(cards)) return Hands.Straight;
        else if(Is3Cards(cards)) return Hands.Three_of_a_kind;
        else if(Is2Pair(cards)) return Hands.Two_pair;
        else if(Is1Pair(cards)) return Hands.One_pair;
        return Hands.No_pair;
    }

    static bool Is5cards(string cards) {
        return IsAnyCards(cards, 5);
    }

    static bool IsRoyalStraightFlush(string cards){
        if(IsFlush(cards) && IsStraight(cards)){
            for(int i = 2; i <= 9; i++) {//2~9までの数字が含まれていたらNG
                if(cards.IndexOf(i.ToString()) != -1) return false;
            }
            return true;
        }
        return false;
    }

    static bool IsStraightFlush(string cards) {
        return IsFlush(cards) && IsStraight(cards);
    }

    static bool Is4cards(string cards) {
        return IsAnyCards(cards, 4);
    }

    static bool IsFullHouse(string cards) {
        return Is3Cards(cards) && Is1Pair(cards);
    }

    static bool IsFlush(string cards) {
        foreach(char suit in Suits.ToCharArray()) {//あるスーツの文字を切り取って
            if(cards.Length - cards.Replace(suit.ToString(),"").Length == 5) return true;
            //5文字減ったら5枚全て同じスーツ
        }
        return false;
    }

    static bool IsStraight(string cards) {
        List<string> rankListInCards = new List<string>();//カードのランクのみ
        //ランク切り出し
        for(int i = 1; i <= 9; i = i + 2) {
            rankListInCards.Add(cards[i].ToString());
        }
        //並び替え
        rankListInCards.Sort(cardRankSort);
        //ソート済みカードリスト作成
        string sortedCards = "";
        foreach(string card in rankListInCards) {
            sortedCards += card;
        }
        //判定
        if(Ranks.Contains(sortedCards)) return true;
        if(sortedCards[0] == 'A') {//先頭がAなら
            //末尾に移してもう一度判定
            if(Ranks.Contains(sortedCards.Remove(0, 1).PadRight(5, 'A'))) return true;
        }
        return false;
    }

    static bool Is3Cards(string cards) {
        return IsAnyCards(cards, 3);
    }

    static bool Is2Pair(string cards) {
        foreach(char Rank in Ranks.ToCharArray()) {
            if(cards.Length - cards.Replace(Rank.ToString(), "").Length == 2) {//One pairだったら
                return Is1Pair(cards.Replace(Rank.ToString(),""));//One pairが2回でTwo pair
            }
        }
        return false;
    }

    static bool Is1Pair(string cards) {
        return IsAnyCards(cards, 2);
    }

    //あるカードがany枚含まれているかどうかを判定
    static bool IsAnyCards(string cards, int any) {
        foreach(char Rank in Ranks.ToCharArray()) {
            if(cards.Length - cards.Replace(Rank.ToString(), "").Length == any) return true;
        }
        return false;
    }

    static int cardRankSort(string x, string y) {
        return Ranks.IndexOf(x) - Ranks.IndexOf(y); 
    }
}

Index

Feed

Other

Link

Pathtraq

loading...