我正在创建一个扑克系统,我正在精简我的手动计算器。
以下代码有效:
public enum CARDS
{
None = 0,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Jack,
Queen,
King,
Ace
};
public enum SUITS
{
None = 0,
Diamonds,
Clubs,
Hearts,
Spades
};
public class Card
{
public CARDS Val { get; set; }
public SUITS Suit { get; set; }
}
public class IntIndex
{
public int Count { get; set; }
public int Index { get; set; }
}
static void Test()
{
List<Card> cardList = new List<Card>();
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Two });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = CARDS.Four });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = CARDS.Five });
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Six });
cardList.Add(new Card { Suit = SUITS.Spades, Val = CARDS.Six });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = CARDS.Seven });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = CARDS.Eight });
// I have a processor that iterates through the above card list and creates
// the following array based on the Card.Val as an index
int[] list = new int[] {0,0,0,1,1,2,1,1,0,0,1,0,0,0};
List<IntIndex> indexList =
list.Select((item, index) => new IntIndex { Count = item, Index = index })
.Where(c => c.Count > 0).ToList();
List<int> newList = (from i in indexList
join j in indexList on i.Index equals j.Index + 1
where j.Count > 0
select i.Index).ToList();
// Add the previous index since the join only works on n+1
// Note - Is there a way to include the first comparison card?
newList.Insert(0, newList[0] - 1);
// Nice! - got my straight card list
List<CARDS> cards = (from l in newList
select (CARDS)l).ToList();
}
但是,我想让它更紧凑,如:
static void Test()
{
List<Card> cardList = new List<Card>();
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Two });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = CARDS.Four });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = CARDS.Five });
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Six });
cardList.Add(new Card { Suit = SUITS.Spades, Val = CARDS.Six });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = CARDS.Seven });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = CARDS.Eight });
List<Card> newList1 = (from i in cardList
join j in cardList on i.Val equals j.Val + 1
select i).ToList();
// Add the previous index since the join only works on n+1
// Similar to: newList1.Insert(0, newList1[0] - 1);
// However, newList1 deals with Card objects so I need
// To figure how to get the previous, non-duplicate card
// from the original cardList (unless there is a way to return the
// missing card!)
}
问题在于Sixes正在重演。不同以及自定义比较功能不起作用,因为这会破坏n + 1连接子句。
另一个问题是以下卡片列表:
List<Card> cardList = new List<Card>();
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Two });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = CARDS.Three });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = CARDS.Five });
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Six });
cardList.Add(new Card { Suit = SUITS.Spades, Val = CARDS.Six });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = CARDS.Seven });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = CARDS.Eight });
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = CARDS.Jack });
我得到3Hearts,6Diamond,7Hearts,8Hearts的回归名单,因为2和3是连续的。
我真正想要的是一个列表,它返回连续5张或更高的卡片,或者更好的是连续序列的前5张牌。因此上面的列表将返回空,因为输入列表中没有5个连续的卡。
答案 0 :(得分:3)
如果您有兴趣从cardList
获取具有最高顺序卡值范围的卡片子集,请考虑这种方法。
//Extension method to find a subset of sequential consecutive elements with at least the specified count of members.
//Comparisions are based on the field value in the selector.
//Quick implementation for purposes of the example...
//Ignores error and bounds checking for purposes of example.
//Also assumes we are searching for descending consecutive sequential values.
public static IEnumerable<T> FindConsecutiveSequence<T>(this IEnumerable<T> sequence, Func<T, int> selector, int count)
{
int start = 0;
int end = 1;
T prevElement = sequence.First();
foreach (T element in sequence.Skip(1))
{
if (selector(element) + 1 == selector(prevElement))
{
end++;
if (end - start == count)
{
return sequence.Skip(start).Take(count);
}
}
else
{
start = end;
end++;
}
prevElement = element;
}
return sequence.Take(0);
}
//Compares cards based on value alone, not suit.
//Again, ignores validation for purposes of quick example.
public class CardValueComparer : IEqualityComparer<Card>
{
public bool Equals(Card x, Card y)
{
return x.Val == y.Val ? true : false;
}
public int GetHashCode(Card c)
{
return c.Val.GetHashCode();
}
}
鉴于上述情况,方法是首先根据卡的价值对卡片进行分类,而不是西装,按降序给出卡片。然后创建不同卡的子集,再次仅基于卡值,不适合。然后调用FindConsecutiveSequence
指定Val属性进行比较,以及有效序列所需的元素数量。
//Sort in descending order based on value of the card.
cardList.Sort((x,y) => y.Val.CompareTo(x.Val));
//Create a subset of distinct card values.
var distinctCardSet = cardList.Distinct(new CardValueComparer());
//Create a subset of consecutive sequential cards based on value, with a minimum of 5 cards.
var sequentialCardSet = distinctCardSet.FindConsecutiveSequence(p => Convert.ToInt32(p.Val), 5);
我认为这应该涵盖你在问题中提出的问题,并为你提供一些建议。但是,如果这对扑克来说,在Ace可以是低值的情况下,这种逻辑将失败 - &gt; {A,2,3,4,5-}。我没有看到提到所需的Ace特定逻辑,所以也许你可以在问题范围之外处理它。
答案 1 :(得分:1)
按编号订购卡片,然后选择1并跳过3,选择你想要的。
答案 2 :(得分:0)
这是你想要的吗?
首先是随机的套装列表,但是顺序列出的牌值
Random random = new Random((int)(DateTime.Now.ToBinary() % Int32.MaxValue));
List<Card> hand = new List<Card>();
for(int card = (int)CARDS.Five;card <= (int)CARDS.Nine;card++)
{
SUIT suit = (SUITS)(random.Next(4)+1);
hand.Add(new Card { Suit = suit, Val = (CARDS)card });
}
或者顺序的诉讼清单是......
for(int card = (int)CARDS.Five, int suit = (int)SUITS.Diamonds;card <= (int)CARDS.Nine;card++, suit++)
{
if(suit > (int)SUITS.Spades)
suit = (int)SUITS.Diamonds;
hand.Add(new Card { Suit = (SUITS)suit, Val = (CARDS)card });
}
答案 3 :(得分:0)
使用Aggregate方法。您可以修改下面的示例代码以返回各种长度的卡片列表,并更改while子句以检查必须匹配的卡片数量。 (例如,我的版本检查Count == 5,您可以检查Count&gt; = 5等)
public class Card {
public CARDS Val { get; set; }
public SUITS Suit { get; set; }
// added ToString for program below
public override string ToString() {
return string.Format("{0} of {1}", Val, Suit);
}
}
class Program {
static IEnumerable<Card> RandomList(int size) {
var r = new Random((int)DateTime.Now.Ticks);
var list = new List<Card>();
for (int i = 0; i < size; i++) {
list.Add(new Card {
Suit = (SUITS)r.Next((int)SUITS.Diamonds, (int)SUITS.Spades),
Val = (CARDS)r.Next((int)CARDS.Two, (int)CARDS.Ace)
});
}
return list.OrderBy(c => c.Val);
}
// generates a random list of 5 cards untill
// the are in sequence, and then prints the
// sequence
static void Main(string[] args) {
IEnumerable<Card> consecutive = null;
do {
// generate random list
var hand = RandomList(5);
// Aggreate:
// the passed in function is run for each item
// in hand. acc is the accumulator value.
// It is passed in to each call. The new List<Card>()
// parameter is the initial value of acc when the lambda
// is called on the first item in the list
// in the lambda we are checking to see if the last
// card in the accumulator value is one less
// than the current card. If so, add it to the
// accumulator, otherwise do not.
consecutive = hand.Aggregate(new List<Card>(), (acc, card) => {
var size = acc.Count != 0
? ((int)card.Val) - ((int)acc[acc.Count - 1].Val)
: 1;
if (size == 1)
acc.Add(card);
return acc;
});
} while (consecutive.Count() != 5);
foreach (var card in consecutive) {
Console.WriteLine(card);
}
Console.ReadLine();
}
}
答案 4 :(得分:0)
以下方法在提供七张牌时(包括A-5的边缘情况)应获得最好的直接手,但我没有彻底测试过。
关键点在于,如果您按照降序对卡片进行排序并删除任何重复的值,则只有几种可能的方式来安排直线(并且您只需要检查四肢):
以下是代码:
public static IEnumerable<Card> GetBestStraight(IEnumerable<Card> sevenCards)
{
if (sevenCards.Count() != 7)
{
throw new ArgumentException("Wrong number of cards", "sevenCards");
}
List<Card> ordered = sevenCards.OrderByDescending(c => c.Val).ToList();
List<Card> orderedAndUnique = ordered.Where((c, i) => i == 0 || ordered[i].Val != ordered[i - 1].Val).ToList();
if (orderedAndUnique.Count < 5)
{
// not enough distinct cards for a straight
return Enumerable.Empty<Card>();
}
if (orderedAndUnique[0].Val == orderedAndUnique[4].Val + 4)
{
// first five cards are a straight
return orderedAndUnique.Take(5);
}
else if (5 < orderedAndUnique.Count && orderedAndUnique[1].Val == orderedAndUnique[5].Val + 4)
{
// next five cards are a straight
return orderedAndUnique.Skip(1).Take(5);
}
else if (6 < orderedAndUnique.Count && orderedAndUnique[2].Val == orderedAndUnique[6].Val + 4)
{
// last five cards are a straight
return orderedAndUnique.Skip(2).Take(5);
}
// if there's an A-5 straight, the above won't have found it (because Ace and Two are not consecutive in the enum)
if (orderedAndUnique[0].Val == CARDS.Ace && orderedAndUnique[orderedAndUnique.Count - 4].Val == CARDS.Five)
{
return orderedAndUnique.Where(c => c.Val == CARDS.Ace || c.Val <= CARDS.Five);
}
return Enumerable.Empty<Card>();
}
答案 5 :(得分:0)
List<Card> cardList = new List<Card>();
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = RANK.Two });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = RANK.Three });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = RANK.Five });
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = RANK.Seven });
cardList.Add(new Card { Suit = SUITS.Hearts, Val = RANK.Four });
cardList.Add(new Card { Suit = SUITS.Clubs, Val = RANK.King });
cardList.Add(new Card { Suit = SUITS.Diamonds, Val = RANK.Ace });
int card = 0;
foreach (Card c in cardList)
{
card |= 1 << (int)c.Val - 1;
}
bool isStraight = false;
RANK high = RANK.Five;
int mask = 0x1F;
while (mask < card)
{
++high;
if ((mask & card) == mask)
{
isStraight = true;
}
else if (isStraight)
{
--high;
break;
}
mask <<= 1;
}
// Check for Ace low
if ((!isStraight) && ((0x100F & card) == 0x100F))
{
isStraight = true;
high = RANK.Five;
}
return card;