ポーカーの役を判定するプログラムをC#で作りました。
私は昔、麻雀の役を判定するアルゴリズムを見たことがあります。ポーカーの役判定も洗練されたアルゴリズムがあると思うのですが、あまりまとまっている情報がありませんでした。
いくつかのサイトで収集した情報を元にC#のプログラムに起こしたので公開します。
ただし、バグはあるかもしれません。
ポーカーのルールについてはポーカー - Wikipediaを参照してください。
// カードの意味
// 1バイトの上位4ビット(0xF0)をスート、下位4ビット(0x0F)をランク、として扱う
//
// A 2 3 4 5 6 7 8 9 10 J Q K
// ♠(スペード): 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D
// ♥(ハート) : 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D
// ♦(ダイア) : 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D
// ♣(クラブ) : 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D
//
/// <summary>
/// 手役
/// </summary>
public enum PokerHand
{
RoyalStraightFlush,
StraightFlush,
FourOfAKind,
FullHouse,
Flush,
Straight,
ThreeOfAKind,
TwoPair,
OnePair,
NoPair,
}
/// <summary>
/// 手役の判断
/// </summary>
/// <param name="cards">手札</param>
/// <returns>手役</returns>
public PokerHand Judge(List<int> cards)
{
// カードが2枚以上ない場合、判定なしで不成立
if (cards.Count() < 2) return PokerHand.NoPair;
// @ペア系の判定
// 各カードとペアになるカードの枚数をカウントする。
// 枚数に応じてペア系の役が確定する。
int count = 0;
for (int i = 0; i < cards.Count() - 1; i++)
{
for (int j = i + 1; j < cards.Count(); j++)
{
if ((cards[i] & 0xF) == (cards[j] & 0xF))
{
count++;
}
}
}
// 成立した役を返す
switch (count)
{
case 1: return PokerHand.OnePair;
case 2: return PokerHand.TwoPair;
case 3: return PokerHand.ThreeOfAKind;
case 4: return PokerHand.FullHouse;
case 6: return PokerHand.FourOfAKind;
}
// ストレート系・フラッシュ系はカード5枚でないと不成立
if (cards.Count() != 5) return PokerHand.NoPair;
// Aストレート系の判定
bool straight = false;
bool royal = false;
// 5つの数字の差が4以内であればストレート成立
{
int max = cards.Max(card => card & 0x0F);
int min = cards.Min(card => card & 0x0F);
if (max - min <= 4)
{
// ストレート成立
straight = true;
}
}
// ストレート不成立の場合はロイヤルストレートの判断を行う。
// エース(A)を14として判定し直す
if (straight == false)
{
int max = cards.Max(card => ((card & 0x0F) == 1) ? 14 : (card & 0x0F));
int min = cards.Min(card => ((card & 0x0F) == 1) ? 14 : (card & 0x0F));
if (max - min <= 4)
{
// ロイヤルストレート成立
straight = true;
royal = true;
}
}
// Bフラッシュ系の判定
bool flush = true;
// 5つのスートが全て同じならフラッシュ成立
for (int i = 1; i < cards.Count(); i++)
{
if ((cards[0] & 0xF0) != (cards[i] & 0xF0))
{
flush = false;
break;
}
}
// 成立した役を返す
if (royal && flush) return PokerHand.RoyalStraightFlush;
if (straight && flush) return PokerHand.StraightFlush;
if (flush) return PokerHand.Flush;
if (straight) return PokerHand.Straight;
// 何も成立しなかった
return PokerHand.NoPair;
}
動作検証のため、FormにTextBoxとRichTextBoxを配置して、検証用プログラムを書きます。検証用なのでかなりの手抜きです。
TextBoxに、手札の数値をスペースで区切って16進数で入力すると、その結果をRichTextBoxに出力します。
private void textBox1_TextChanged(object sender, EventArgs e)
{
// テキストボックスに入力した数値をリストに格納する。
// 文字列→数値の変換は結構手抜き
List<int> cards = new List<int>();
foreach (string text in this.textBox1.Text.Split(' '))
{
try { cards.Add(int.Parse(text, System.Globalization.NumberStyles.AllowHexSpecifier)); }
catch { }
}
// 役の判定
PokerHand hand = Judge(cards);
// 結果出力
StringBuilder sb = new StringBuilder();
string[] suit = new string[] { "♠", "♥", "♦", "♣" };
string[] rank = new string[] { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
foreach (int c in cards)
{
try
{
sb.Append(
suit[((c & 0xF0) >> 4) - 1] +
rank[(c & 0x0F) - 1]);
}
catch { }
}
sb.Append(
System.Environment.NewLine +
hand.ToString());
richTextBox1.Text = sb.ToString();
}
実行結果は次のようになります。
手札の順番はバラバラでも問題ありません。
良かったらクリックしてください
posted by among at 20:30
|
Comment(0)
|
TrackBack(0)
|
ゲーム制作