C# i可比较且有序。尝试用C对扑克手进行排序#

C# i可比较且有序。尝试用C对扑克手进行排序#,c#,poker,icomparer,C#,Poker,Icomparer,我试图创建一个简单的程序来分析扑克牌。考虑到n手牌/玩家和社区卡(德克萨斯州持有),我想确定赢家。然而,当我有两个确切的结果时,我的测试失败了——它只返回一个获胜者。i、 e对于两位选手,手牌结果都包含J 9 K,但我的获奖名单包含一个 我在这里发帖有几个原因。显然,首先,这里有什么明显的错误吗?这是一种实现排序的好方法吗(我看不出将排序分开的原因),有更好的方法吗?为什么 我有一个DetermineWinners方法,它对玩家的HandResult执行命令: var ordered = _pl

我试图创建一个简单的程序来分析扑克牌。考虑到n手牌/玩家和社区卡(德克萨斯州持有),我想确定赢家。然而,当我有两个确切的结果时,我的测试失败了——它只返回一个获胜者。i、 e对于两位选手,手牌结果都包含J 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;
    }
}
这是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_GreateThan(使用我的运算符重载)的测试成功,结果分别为0、-1和1。我相信这是我的Linq.OrderByDescending实现的问题。我认为这只是使用比较来实现,我错了吗?

IComparable
提供的比较(无论如何,您应该使用通用版本
IComparable
)仅通过接口方法
int CompareTo(IComparable other)
表示,其结果是

  • 如果当前对象大于
    other

  • <0如果当前对象小于
    other
  • =0表示相等

重载的比较运算符对于依赖于
IComparable

的任何代码都不重要。您正试图通过选择结果与最佳手的结果相同的代码来选择赢家,但只有当手完全相同时才是如此(我想,在不知道cardGroup[I]到底是什么的情况下,我很难看到整个画面

你确定你期望的完全相同的手实际上是完全相同的(甚至在同一套衣服里)


然后我还建议您根据其他运算符实现大多数运算符重载。例如!=可以实现为!(=)(反转调用==运算符的结果,而不是重新实现整个条件集-现在,如果更改确定等于的方式,则必须在中复制这些更改!)

谢谢您的回复!我似乎没有正确粘贴代码。我编辑了我的帖子以反映完整的HandResult类,我还使用了IComparable的通用版本。也就是说,我的测试仍然失败。我在键入答案时看到您的原始代码被编辑,但我恐怕现在没有时间查看它和upda请依次回答我的问题。感谢您的回答。很抱歉,代码编辑之前没有全部内容。是的,赢家是由拥有最佳手牌的玩家决定的。我已覆盖.Equals和==运算符以检查牌的值,因此它不包括套件。cardGroup[I]只有当HandRank相同时,节才会命中,在这种情况下,它将遍历值,并在构成手牌的5张卡上进行比较。
    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 };
        }
    }