我正在尝试创建一个分析扑克手的简单程序。鉴于n手/球员和社区卡(德州扑克),我想确定获胜者。但是,当我有两个确切的结果时,我的测试失败了 - 它只返回一个赢家。即两名球员的手牌结果包含J J 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实现,我错了吗?
答案 0 :(得分:3)
IComparable
提供的比较(您应该使用通用版本IComparable<T>
)仅通过接口方法int CompareTo(IComparable other)
表示,其结果为
如果当前对象大于other
,则0
other
重载的比较运算符与依赖IComparable
的任何代码无关。
答案 1 :(得分:0)
你试图通过选择那些结果等于最佳手牌结果的人来选择获胜者,但只有当手完全相同时才会这样(我想,我遇到了麻烦)看不到整个画面而不知道cardGroup [i]究竟是什么。
你确定你期望相同的手实际上是相同的吗(甚至同样的套装)?
然后我还建议您根据其他运算符实现大多数运算符重载。例如,!=可以实现为!(==)(反转调用==运算符的结果,而不是重新实现整组条件 - 现在,如果你改变Equals的方式确定你将不得不在!=)
中复制这些更改