【问题标题】:Comparing Multiple Objects In Single List比较单个列表中的多个对象
【发布时间】:2018-08-18 16:48:19
【问题描述】:

这可能是重复的,但我已经找了几个小时了,但我一直在做空。所以这里是:

I don't have any code yet. I got p*ssed and deleted most of it! :P

我正在编写一个简单的程序,它将从一副纸牌中抽出五张牌。现在,我可以做到。但是,我正在制作一个按钮,它将不断从新牌组中抽牌,直到碰到一对。

现在的问题是五张抽出的牌的比较。我正在从列表中绘制它们

List<Card> TheDeck

并将它们添加到另一个列表中

List<Card> TheHand

卡片类非常简单,只包含花色​​的第一个字母和一个数字。

public string suit;
public int number;
public Card(string suit, int number)
{
    this.suit = suit;
    this.number = number;
}

现在要抽一对,我必须比较抽出的五张牌的数字,看是否有任何匹配。我这样做的最后一种方法是执行 GIANT if 语句,

if (TheHand[0].number == TheHand[1].number || 
TheHand[0].number == TheHand[2].number || TheHand[0].number == TheHand[3].number || 
TheHand[0].number == TheHand[4].number /* .. and so on and so on .. */)

我可以这样做,但它似乎太过分了。 所以你有我的问题。比较所有卡片的更简单方法是什么?任何帮助将不胜感激。

【问题讨论】:

  • 我会使用 LINQ 的 GroupBy 按卡片编号对卡片进行分组,然后查看每组中有多少张卡片。我还建议对西装使用枚举而不是字符串,并使用属性而不是字段。
  • 几个问题:你有不止一副牌吗?如果没有,我会在您的 Card 对象上使用 IComparable 。如果您想了解更多信息,我会为您解答。
  • @Aldert - 我有一副牌,如果它在第一次尝试时未能抽出一对,我会重新洗牌并重新抽牌。
  • 大图:.NET 集合很聪明地使用Equals、CompareTo、IEquatable、&IComparable;并且不会被继承、覆盖或实现接口的混合混淆。请参阅 MSDN for List methods,如 Contains、Find、BinarySearch、Sort 等。花点时间阅读 MSDN 中的 IEquatable 和 IComparable。您无需了解所有内容即可使用它。

标签: c# c#-4.0


【解决方案1】:

您还可以让您的 Card 类继承自 IEqutable,并使用 Equals 方法定义如何确定两张卡是否成对,然后按照 Selman 的建议使用 Linq.GroupBy,但这次没有为 groupBy 指定任何条件. input.GroupBy(c =&gt; c).Where(g =&gt; g.Count() &gt; 1) 代码如下,以及一些测试方法:

     public class Card : IEquatable<Card>
        {
            public string suit;
            public int number;

            public Card(string suit, int number)
            {
                this.suit = suit;
                this.number = number;
            }

            public bool Equals(Card other)
            {
                if (ReferenceEquals(other, null))
                {
                    return false;
                }
                return Equals(number, other.number);
            }

            public override int GetHashCode()
            {
                return number.GetHashCode();
            }

        }

        public class FindCardPairs
        {
            public static List<IGrouping<Card, Card>> FindAllPairs(List<Card> input)
            {
                List<IGrouping<Card,Card>> allPairs =  input.GroupBy(c => c).Where(g => g.Count() > 1).ToList();
                return allPairs;
            }
        }

[TestMethod]
        public void Card_Test_Equality()
        {
            var card1 = new Card(string.Empty, 2);
            var card2 = new Card("card2", 2);

            Assert.IsTrue(card1.Equals(card2));
        }

        [TestMethod]
        public void Test_FindAllPairs()
        {
            var cards = new List<Card>
            {
                new Card(string.Empty, 2),
                new Card("card2", 2)
            };

            List<IGrouping<Card, Card>> actual = FindCardPairs.FindAllPairs(cards);
            Assert.IsTrue(actual.Any());
            Assert.AreEqual(1, actual.Count());

        }

【讨论】:

  • 推荐:在实现IEquatable 时覆盖Object.Equals,以确保两者评估相等的方式相同。
【解决方案2】:

您可以按编号对卡片进行分组,并检查是否有任何组拥有一张以上的卡片:

TheHand.GroupBy(c => c.number).Any(g => g.Count() > 1)

要选择匹配的卡片,您可以使用Where:

TheHand.GroupBy(c => c.number).Where(g => g.Count() > 1).SelectMany(g => g);

【讨论】:

    【解决方案3】:

    根据您正在创建的游戏,您可以独立评价您的卡片。目前,卡片按编号进行比较,详情见:https://docs.microsoft.com/en-us/dotnet/api/system.icomparable?redirectedfrom=MSDN&view=netframework-4.7.2

    CardComparer 可用于对卡片进行排序,我先按花色排序,然后按数字排序,根据游戏您可能会决定更改此设置,记住在比较卡片时,您总是比较 2,因此您的比较规则是很好地包含在 Compare 方法中。

    在手上添加物品时,可以使用以下方式:

    int index = TheHand.BinarySearch(newCard);
    if (index>-1) //now a card with same number is found and you can take action
    else
    TheHand.Add(newCard);
    

    这里是类代码:

    public class Card : IComparable<Card>
            {
                public Card(string suit, int number)
                {
                    this.Suit = suit;
                    this.Number = number;
                }
    
                public string Suit { get; }
                public int Number { get; }
    
                public int CompareTo(Card other)
                {
                    return Number.CompareTo(other.Number);
                }
            }
    

    额外让您更好地理解这个概念:用于排序:TheHand.Sort(new CardComparer());

            public class CardComparer : IComparer<Card>
            {
                public int Compare(Card x, Card y)
                {
                    int compResult = x.Suit.CompareTo(y.Suit);
                    if (compResult == 0)
                    {
                        compResult = x.Number.CompareTo(y.Number);
                    }
                    return compResult;
                }
            }
    

    注意:当黑桃皇后最强时,您可以将此逻辑添加到比较器中。例如。您可以制作一个游戏比较器来比较桌上的牌。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-26
      • 2017-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-19
      相关资源
      最近更新 更多