Сформировать все отдельные комбинации из 7 карт покерной руки?
Я пытаюсь сгенерировать все различные комбинации покерной руки, как описано здесь:
Генерация всех пятикарточных покерных комбинаций
Но я продолжаю застрять. И при попытке ответа Cick от NickLarsen по указанному выше URL я получаю необработанную ошибку исключения в строке 49. ( /questions/31374487/generatsiya-vseh-pyatikartochnyih-pokernyih-kombinatsij/31374500#31374500)
То, что я хочу, очень просто: генерировать все комбинации карточек и печатать их по одной строке за раз в простом текстовом файле.
Кроме того, я на самом деле хочу все 7 карточных комбинаций (вместо 5). Например, первые две строки могут выглядеть так:
2c2d2h2s3c3d3h
2c2d2h2s3c3d3s
Как мне этого добиться? Скорость не так важна.
Ниже приведен код от NickLarsen (с моими изменениями), который не работает:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication20
{
struct Card
{
public int Suit { get; set; }
public int Rank { get; set; }
}
class Program
{
static int ranks = 13;
static int suits = 4;
static int cardsInHand = 7;
static void Main(string[] args)
{
List<Card> cards = new List<Card>();
//cards.Add(new Card() { Rank = 0, Suit = 0 });
int numHands = GenerateAllHands(cards);
Console.WriteLine(numHands);
Console.ReadLine();
}
static int GenerateAllHands(List<Card> cards)
{
if (cards.Count == cardsInHand) return 1;
List<Card> possibleNextCards = GetPossibleNextCards(cards);
int numSubHands = 0;
foreach (Card card in possibleNextCards)
{
List<Card> possibleNextHand = cards.ToList(); // copy list
possibleNextHand.Add(card);
numSubHands += GenerateAllHands(possibleNextHand);
}
return numSubHands;
}
static List<Card> GetPossibleNextCards(List<Card> hand)
{
int maxRank = hand.Max(x => x.Rank);
List<Card> result = new List<Card>();
// only use ranks >= max
for (int rank = maxRank; rank < ranks; rank++)
{
List<int> suits = GetPossibleSuitsForRank(hand, rank);
var possibleNextCards = suits.Select(x => new Card { Rank = rank, Suit = x });
result.AddRange(possibleNextCards);
}
return result;
}
static List<int> GetPossibleSuitsForRank(List<Card> hand, int rank)
{
int maxSuit = hand.Max(x => x.Suit);
// select number of ranks of different suits
int[][] card = GetArray(hand, rank);
for (int i = 0; i < suits; i++)
{
card[i][rank] = 0;
}
int[][] handRep = GetArray(hand, rank);
// get distinct rank sets, then find which ranks they correspond to
IEnumerable<int[]> distincts = card.Distinct(new IntArrayComparer());
List<int> possibleSuits = new List<int>();
foreach (int[] row in distincts)
{
for (int i = 0; i < suits; i++)
{
if (IntArrayComparer.Compare(row, handRep[i]))
{
possibleSuits.Add(i);
break;
}
}
}
return possibleSuits;
}
class IntArrayComparer : IEqualityComparer<int[]>
{
#region IEqualityComparer<int[]> Members
public static bool Compare(int[] x, int[] y)
{
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i]) return false;
}
return true;
}
public bool Equals(int[] x, int[] y)
{
return Compare(x, y);
}
public int GetHashCode(int[] obj)
{
return 0;
}
#endregion
}
static int[][] GetArray(List<Card> hand, int rank)
{
int[][] cards = new int[suits][];
for (int i = 0; i < suits; i++)
{
cards[i] = new int[ranks];
}
foreach (Card card in hand)
{
cards[card.Suit][card.Rank] = 1;
}
return cards;
}
}
}
3 ответа
Это потому что вы закомментировали //cards.Add(new Card() { Rank = 0, Suit = 0 });
, Ваш cards
список пуст, и ваш код не может найти max
пустого массива - это предсказуемо.
Я немного опоздал на вечеринку, но имел такую же потребность (для пятикарточных покерных комбинаций). Также работая с ответом Ника Ларсена (казалось бы, несовершенным, поскольку я тоже получаю неправильный номер) в другом потоке, просто добавьте метод, чтобы получить имя карты (я уверен, что кто-то может сделать это более элегантно, но это работает):
static string GetCardName(Card card)
{
string cardName;
string cardFace;
string cardSuit;
switch (card.Rank)
{
case 0:
cardFace = "2";
break;
case 1:
cardFace = "3";
break;
case 2:
cardFace = "4";
break;
case 3:
cardFace = "5";
break;
case 4:
cardFace = "6";
break;
case 5:
cardFace = "7";
break;
case 6:
cardFace = "8";
break;
case 7:
cardFace = "9";
break;
case 8:
cardFace = "10";
break;
case 9:
cardFace = "J";
break;
case 10:
cardFace = "Q";
break;
case 11:
cardFace = "K";
break;
default:
cardFace = "A";
break;
}
switch (card.Suit)
{
case 0:
cardSuit = "H";
break;
case 1:
cardSuit = "D";
break;
case 2:
cardSuit = "S";
break;
default:
cardSuit = "C";
break;
}
cardName = cardFace + cardSuit;
return cardName;
}
Затем используйте это в цикле for, чтобы вы могли распечатать его или все, что вам нужно:
static void Main(string[] args)
{
List<Card> cards = new List<Card>();
cards.Add(new Card() { Rank = 0, Suit = 0 });
int numHands = GenerateAllHands(cards);
int counter = 0;
Console.WriteLine(numHands);
Console.WriteLine(possibleHands.Count);
foreach (Hand hand in possibleHands)
{
counter += 1;
foreach (Card card in hand.Cards)
{
hand.HandString += GetCardName(card) + " ";
}
hand.HandString = hand.HandString.Trim();
}
Console.ReadLine();
}
Это занимает около 3 секунд
Зачем записывать их в текстовый файл
Вы можете генерировать их быстрее, чем вы могли читать из файла
public void PokerHands7from52()
{
for (byte i = 0; i < 52; i++)
Debug.WriteLine("rank " + i % 13 + " suite " + i / 13);
Stopwatch sw = new Stopwatch();
sw.Start();
int counter = 0;
for (int i = 51; i >= 6; i--)
{
for (int j = i - 1; j >= 5; j--)
{
for (int k = j - 1; k >= 4; k--)
{
for (int m = k - 1; m >= 3; m--)
{
for (int n = m - 1; n >= 2; n--)
{
for (int p = n - 1; p >= 1; p--)
{
for (int q = p - 1; q >= 0; q--)
{
// the 7 card are i, j, k, m, n, p, q
counter++;
if (counter % 10000000 == 0)
Debug.WriteLine(counter.ToString("N0") + " " + sw.ElapsedMilliseconds.ToString("N0"));
}
}
}
}
}
}
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("counter " + counter.ToString("N0") + " should be 133,784,560");
System.Diagnostics.Debug.WriteLine("sw " + sw.ElapsedMilliseconds.ToString("N0"));
}
}