我正在尝试创建一个分析扑克手的简单程序。给定 n 手/玩家和公共牌(德州扑克),我想确定获胜者。但是,当我有两个确切的结果时,我的测试失败了——它只返回一个获胜者。即手牌结果包含 JJ 9 9 K,对于两个玩家,但我的获胜者列表包含一个。
我在这里发帖有几个原因。显然,第一个是这里有什么明显的错误吗?这是实现排序的好方法(我看不出分开排序的理由),是否有更好的方法,为什么?
我有一个DetermineWinners 方法,它正在对玩家的HandResult 执行订单:
var ordered = _players.OrderByDescending(player => player.Result);
var bestHand = ordered.First();
var winners = ordered.Where(s => s.Result == bestHand.Result).ToList();
这是我的手结果类:
public class HandResult : IComparable<HandResult>
{
public Hand WholeCards { get; set; }
public HandRanking HandRank { get; set; }
public IEnumerable<Card> CommunityCards { get; set; }
public IEnumerable<Card> UsedCards { get; set; }
public static bool operator !=(HandResult a, HandResult b)
{
if (a == null)
return b != null;
if (b == null)
return true;
if (a.HandRank != b.HandRank)
return true;
//Compare Used Cards
var aCards = a.UsedCards.Select(s => s.GetCardValue()).ToList();
var bCards = b.UsedCards.Select(s => s.GetCardValue()).ToList();
var cardGroup = a.HandRank.GetGrouping();
for (int i = 0; i < 5; i += cardGroup[i])
{
if (aCards[i] != bCards[i])
return true;
}
return false;
}
public static bool operator ==(HandResult a, HandResult b)
{
if ((object)a == null)
return (object)b == null;
if ((object)b == null)
return false;
if (a.HandRank != b.HandRank)
return false;
var aCards = a.UsedCards.Select(s => s.GetCardValue()).ToList();
var bCards = b.UsedCards.Select(s => s.GetCardValue()).ToList();
var cardGroup = a.HandRank.GetGrouping();
for (int i = 0; i < 5; i += cardGroup[i])
{
if (aCards[i] != bCards[i])
{
return false;
}
}
return true;
}
public static bool operator >(HandResult a, HandResult b)
{
if ((object)a == null)
return (object)b != null;
if ((object)b == null)
return false;
if ((object)a == (object)b)
return false;
if (a.HandRank != b.HandRank)
return a.HandRank > b.HandRank;
if (a == b)
return false;
var aCards = a.UsedCards.Select(s => s.GetCardValue()).ToList();
var bCards = b.UsedCards.Select(s => s.GetCardValue()).ToList();
var cardGroup = a.HandRank.GetGrouping();
for (int i = 0; i < 5; i += cardGroup[i])
{
if (aCards[i] != bCards[i])
{
return aCards[i] > bCards[i];
}
}
return false;
}
public static bool operator <(HandResult a, HandResult b)
{
if ((object)a == null)
return (object)b == null;
if ((object)b == null)
return true;
if ((object)a == (object)b)
return false;
if (a.HandRank != b.HandRank)
return a.HandRank < b.HandRank;
var aCards = a.UsedCards.Select(s => s.GetCardValue()).ToList();
var bCards = b.UsedCards.Select(s => s.GetCardValue()).ToList();
var cardGroup = a.HandRank.GetGrouping();
for (int i = 0; i < 5; i += cardGroup[i])
{
if (aCards[i] != bCards[i])
return aCards[i] < bCards[i];
}
return false;
}
#region IComparable<HandResult> Members
public int CompareTo(HandResult other)
{
if (this == null)
return other == null ? 0 : -1;
if (other == null)
return 1;
if (this == other)
return 0;
if (this > other)
return 1;
return -1;
}
#endregion
public override bool Equals(object obj)
{
return this == (HandResult)obj;
}
public override int GetHashCode()
{
var result = 0;
result = (result * 397) ^ (int)this.HandRank;
foreach (var card in this.UsedCards)
{
result = (result * 397) ^ card.GetHashCode();
}
return result;
}
}
GetCardResult 方法简单地返回卡片的整数表示,即 1 到 14。这是 HandRanking 枚举:
public enum HandRanking
{
HighCard,
Pair,
TwoPair,
ThreeOfAKind,
Straight,
Flush,
FullHouse,
FourOfAKind,
StraightFlush,
RoyalFlush
}
这是 HandRanking 枚举上的 GetGrouping 扩展。它用于在比较值时帮助遍历卡片:
internal static int[] GetGrouping(this HandRanking rank)
{
switch (rank)
{
case HandRanking.Pair:
return new int[] { 2, 0, 1, 1, 1 };
case HandRanking.TwoPair:
return new int[] { 2, 0, 2, 0, 1 };
case HandRanking.ThreeOfAKind:
return new int[] { 3, 0, 0, 1, 1 };
case HandRanking.FullHouse:
return new int[] { 3, 0, 0, 2, 0 };
case HandRanking.FourOfAKind:
return new int[] { 4, 0, 0, 0, 1 };
default:
return new int[] { 1, 1, 1, 1, 1 };
}
}
非常感谢您的帮助。
编辑:我对 CompareTo_Equal、CompareTo_LessThan 和 CompareTo_GreaterThan(使用我的运算符重载)的测试成功,结果分别为:0、-1 和 1。我相信这是我的 Linq.OrderByDescending 实现的问题。我想这只是使用 CompareTo 实现,我错了吗?