如何在 Unity3D 中查找列表中的 3 个元素是否相同

How to find if 3 elements in list are same in Unity3D

我正在统一开发纸牌游戏。我有 5 张不同的卡片(A、B、C、D、E),我手上最多可以有 6 张卡片。我有一个按钮。所以一旦我抽出一张卡片就点击按钮。所以所有这些功能都准备好了。但是我想在抽出的那些牌中执行一个动作。如果任意三张牌相似。

例如:- 我抽出 5 张牌 抽出的牌顺序是:A,A,A,B,C 现在如你所见,我有 3- A 我想执行 A 动作。或者如果卡片是这样的 A、B、C、C、C、E 如果想要执行 C 功能,因为有 3 个 C。因此,如果 3 张卡片类型相同,我想执行与其相关的操作。

所以为了更简要一点,我将解释一次流程。 Card-Draw 按钮单击 -> 每次点击继续获取卡片 -> 将卡片添加到名为 _CardList 的列表中并对列表中的卡片进行排序 -> 如果有 3 张相同的卡片,则执行一个操作。我在最后一次检查卡时遇到问题。

我已经做了一个方法,但是太庞大了,不可取。所以如果你们能在这方面帮助我,那将对我有很大帮助。谢谢,我会 post 我在下面对我尝试过的所有疑虑和问题。

Try#1
Have multiple list like:
List<Card> Alist;
List<Card> BList; //and so on until And keep creating list as long as card type
.
.
List<Card> Elist;

void DrawButton() // Function thats passed to the button. Meaning what to happen when the button is clicked
{
//Here we instantiate the card randomly from a list given from inspector.

 GameObject card = Instantiate(cards._cardModel, _playerHandPoints[clicks].localPosition, _playerHandPoints[clicks].localRotation, mCardHolderParent.transform);
 
 //We access the card script attached to card and give its type and everything 
 card.GetComponent<Cards>()._cardType = cards._cardType;
 
 //Here we pass the instantiated card
 AddNewCard(card.GetComponent<Cards>());

 //Every time after adding we check if any list count is 3 and perform related action
 CardMatchThreeChecker();
}

AddNewCard(Card inNewCard)
{ 
//in this function we check the card type and add it to their specific list & also add it to _cardList.
  switch (inNewCard._cardType)
        {
            case CardType.A: AList.Add(inNewCard);
                break;
            case CardType.B: BList.Add(inNewCard);
                break;
            case CardType.C: CList.Add(inNewCard);
                break;
            case CardType.D: DList.Add(inNewCard);
                break;
            case CardType.E: EList.Add(inNewCard);
                break;
              default:
                break;

        }
  _CardList.Add(inNewCard);
}
 void CardMatchThreeChecker()
{
        if (AList.Count == 3)
        {
            SceneManager.LoadScene(1);
        }
        if (BList.Count == 3)
        {
            SceneManager.LoadScene(2);
        }
        if (CList.Count == 3)
        {
            SceneManager.LoadScene(3);
        }
        if (DList.Count == 3)
        {
            SceneManager.LoadScene(4);
        }
        if (EList.Count == 3)
        {
            SceneManager.LoadScene(5);
        }
}


问题 - 1:如果我以后添加任何新卡,我需要继续添加许多列表,这是不可取的,因为一次可玩的卡也可以达到或超过 20

问题-2:没有使用包含所有实例化卡片的列表“_cardList”。

问题 - 1 相反,我想检查 _CardList 列表本身是否有任何 3 项相似。就像每次我画一张卡片时,他们都会去并将自己添加到卡片列表的列表中,我想检查列表中是否有任何三个元素相似,然后执行相关操作。我在互联网上进行了搜索,但找不到或不知道该做什么或如何尝试。

但是我尝试了一种方法,但现在我陷入了下面提到的too.Method

These lines below come under a function called CardChecking() That is called in DrawButton(). Here Im saying it to check the list only if card count is more than 2 because we have a match only if 3 cards are there and we cant have a match if cards are less that 3 as we are checking if there are 3 similar cards. And as we want to check the elements of the list we have a for loop with (i,i+1,i+2) making it checking elements of the cardlist. Problem of this outside the snippet.

for (int i = 0; i < _CardList.Count; i++)
        {
            if (_CardList.Count > 2)
            {
                if(_CardList[i]._cardType == _CardList[i+1]._cardType && _CardList[i + 1]._cardType == _CardList[i+2]._cardType)
                {
                  SceneManager.LoadScene(_CardList[i]._cardType.ToString());
                }
                else
                {
                    continue;
                }
            }
        }

我面临的问题是:例如,如果我抽了 3 张牌,我的卡片列表计数将是 3,这将满足我的条件并检查功能。如果我的卡片不是同一类型,那么它会转到下一步进行迭代,那时我的 i 值将是 cardList[1] ||卡片列表[2] && 卡片列表[2] || cardList[3] 表示我的 for 循环第二次迭代时我的卡片值为 1,2 和 3 但是当它检查 cardList[3] 时它抛出索引超出范围因为我的卡片列表计数是 3 并且它没有第 4 个元素for 循环正在检查。所以不知道如何克服这个问题。

我假设卡片的顺序无关紧要,并且认为您正在寻找 Linq GroupBy

// Just a simplified example since you didn't show your Card class
class Card
{
    public CardType _cardType;

    public Card(CardType type)
    {
        _cardType = type;
    }
}


var list = new List<Card> 
{ 
    new Card(CardType.A), 
    new Card(CardType.B), 
    new Card(CardType.C), 
    new Card(CardType.C),
    new Card(CardType.B), 
    new Card(CardType.B),
    new Card(CardType.A), 
    new Card(CardType.A), 
    new Card(CardType.B) 
};

// This creates separated groups according to the value of the card
var groups = list.GroupBy(c => c._cardType)
    // Then it filters out only those groups that have 3 or more items
   .Where(g => g.Count() >= 3);

// Then you can simply iterate through them
foreach (var @group in groups)
{
    // The Key is the value the grouping was based on 
    // so in this example the Card._cardType
    Debug.Log($"There are {@group.Count()} cads with cardType = {@group.Key}");

    // you can also get all the according cards if needed
    //var cards = @group.ToArray();
}

将打印

There are 3 cards with cardType = A
There are 4 cards with cardType = B

此外,如果您只想获得第一个具有 3 项的组,并且无论如何已经知道永远不会同时有两个或更多项,您可以去

// again first create separate groups based on the value
var group = list.GroupBy(c => c._cardType)
    // Pick the first group that has at least 3 items
    // or NULL if there is none
    .FirstOrDefault(g => g.Count() >= 3);

if (group != null)
{
    Debug.Log($"Found a group of {group.Count()} for the value = {group.Key}!");
}
else
{
    Debu.Log("There is no group with 3 elements yet...");
}

要解决问题 - 1,您可以使用 Dictionary :

    Dictionary<CardType,List<Card>> cardListDictionary = new Dictionary<CardType, List<Card>>();
    
    AddNewCard(Card inNewCard)
    {
        if (!cardListDictionary.TryGetValue(inNewCard._cardType,out var list))
        {
            list = new List<Card>();
            cardListDictionary.Add(inNewCard._cardType,list);
        }
        list.Add(inNewCard);
    }

为了解决问题 - 2,像这样实现 CardChecking :

void CardChecking()
    {
        if (_CardList.Count > 2)
        {
            var type = _CardList[0]._cardType;
            var count = 1;
            for (int i = 1; i < _CardList.Count; i++)
            {
                if(_CardList[i]._cardType == type)
                {
                    count++;
                    if (count == 3)
                    {
                        SceneManager.LoadScene(type.ToString());
                    }
                }
                else
                {
                    type = _CardList[i]._cardType;
                    count = 1;
                }
            
            }
        }
    }

嗯,不确定我是否理解了整个画面。让我把问题简化一下,如果可行,那么就有解决方案了。

问题: 我有一个卡片列表,如果列表中有3个相同类型的卡片实例,我需要执行一个动作

答案:使用Linq按类型对列表进行分组。然后,过滤结果以找到“三张牌的情况”。

给你:

var answer = _CardList
    .GroupBy(c => c.GetCardType())
    .ToDictionary(g => g.Key, g => g.Count()) // Count by the card type.
    .Where(x => x.Value >= 3) // Three or more cards of the same type.
    .Select(x => x.Key) // Fetch the card type.
    .FirstOrDefault(); // Only one match is needed.
if (answer != null) {
  // answer is the type of the card that is counted 3 or more times.
}

如果您需要检测所有“三张牌情况”,请移除FirstOrDefault并处理集合。