0

好的,我现在已经在我的头上砸了。

我有两个自定义对象列表,两个列表中的一个属性相同。我需要遍历两个列表并查看属性是否相同。

我可以用嵌套的 for-each 循环来做到这一点,但如果我能用 LINQ 做同样的事情,我很不情愿(我确信我能做到)。我几乎尝试了所有方法,但我根本无法找到我正在寻找的解决方案。

这是我用于列表的对象的代码。

public class Game
{
    // Fields
    private short maxPlayers;
    private Team axis;
    private Team allies;

    // Properties
    public string Name { get; set; }
    public short MaxPlayers
    {
        get
        {
            return maxPlayers;
        }
        set
        {
            if (value > 8)
                maxPlayers = 8;
            else if (value < 2)
                maxPlayers = 2;
            else
                maxPlayers = value;
        }
    }
    public short CurrentPlayers
    {
        get
        {
            int players = axis.Players.Count + allies.Players.Count;
            return (short)players;
        }
    }
    public bool IsFull
    {
        get
        {
            if (CurrentPlayers == MaxPlayers)
                return true;
            else
                return false;
        }
    }
    public Team Axis { get; set; }
    public Team Allies { get; set; }
    public List<Player> Players
    {
        // Somehow this does not work either, so I had to stick with one single team in the for-each loops. Ideas to fix?
        get
        {
            if (allies.Players.Count == 0)
                return axis.Players.Concat(allies.Players).ToList();
            else
                return allies.Players.Concat(axis.Players).ToList();

        }
    }

    //Constructor
    public Game()
    {
        axis = new Team();
        allies = new Team();
    }
}

public class Team
{
    public List<Player> Players { get; set; }

    public EFaction Faction { get; set; }

    public enum EFaction
    {
        Allies,
        Axis,
        Random
    }

    public Team()
    {
        Players = new List<Player>();
        Faction = EFaction.Random;
    }
}

public class Player
{
    private int skillRange = 200;

    public string Name { get; set; }
    public int Skill { get; set; }
    public int SkillRange
    {
        get
        {
            return skillRange;
        }
        set
        {
            if (value >= 200)
                skillRange = value;
            else
                skillRange = 200;
        }
    }
}

在启动时,我从数据库中填充列表并对列表执行相同操作。我想要做的是遍历游戏列表并将游戏中每个玩家的技能属性与团队中每个玩家的技能属性进行比较。这是我使用的 for-each 循环。这行得通。但是你清楚地可以看到我为什么要如此糟糕地削减它。

        // Loop through each player in the Automatch queue.
        foreach (Team team in match.TeamsInQueue)
        {
            // Loop through every game in the Atomatch queue.
            foreach (Game game in match.AvailableGames)
            {
                int teamPlayersInSkillRange = 0;

                // Loop through every player in the team and loop through every player in the game.
                foreach (Player teamPlayer in team.Players)
                {
                    int gamePlayersInSkillRange = 0;
                    foreach (Player gamePlayer in game.Allies.Players)
                    {
                        // Compare beoth skill values. If they are in a certain range increase the counter.
                        if (Math.Abs(teamPlayer.Skill - gamePlayer.Skill) <= 200) // The range is currently set for 200, but I want to make it variable later.
                            gamePlayersInSkillRange++;
                    }

                    // Check if the player in the team is in skill range of the game he wants to join. If yes increase the counter.
                    if (gamePlayersInSkillRange == game.Allies.Players.Count)
                        teamPlayersInSkillRange++;
                  }
                // Check if the whole team is in skill range of the game they want to join. If yes return true.
                if (teamPlayersInSkillRange == team.Players.Count)
                {
                    // ToDo: Implement join process here.
                }
            }
        }

任何帮助,将不胜感激。谢谢。

4

2 回答 2

2

对于给定的球队和比赛,如果球队的所有球员都在所有比赛球员的技能范围内,您希望球队加入比赛。这听起来像是All()方法的工作!

// Loop through each player in the Automatch queue.
foreach (Team team in match.TeamsInQueue)
{
    // Loop through every game in the Atomatch queue.
    foreach (Game game in match.AvailableGames)
    {
        bool allInSkillRange = team.Players.All(t =>
            game.Allies.Players.All(g => Math.Abs(t.Skill - g.Skill) <= 200));
        if(allInSkillRange)
        {
            // ToDo: Implement join process here.
        }
    }
}

如果您对将代码转换为 LINQ 的自动化方式感兴趣,请查看Resharper

以下是我提出解决方案的方法。使用此过程并熟悉 LINQ 的方法并获得经验可以使重构变得更加容易。我不只是看代码并立即想到使用All(). 我从重构较小的部分开始,然后从那里开始。在阅读完所有代码后,我专注于最内层的循环。

int gamePlayersInSkillRange = 0;
foreach (Player gamePlayer in game.Allies.Players)
{
    // Compare beoth skill values. If they are in a certain range increase the counter.
    if (Math.Abs(teamPlayer.Skill - gamePlayer.Skill) <= 200) // The range is currently set for 200, but I want to make it variable later.
        gamePlayersInSkillRange++;
}

这会计算满足条件的玩家数量,可以将其重构为Count()调用:

int gamePlayersInSkillRange = game.Allies.Players.Count(g => 
    (Math.Abs(teamPlayer.Skill - g.Skill) <= 200);

下面的 if 语句检查 gamePlayersInSkillRange 是否等于 game.Allies.Players 中的项目数,这是我们最初计算的列表。哦,所以我们正在检查所有这些列表成员是否都满足谓词!我们可以通过更改Count()All(). 这是下一个最里面的循环现在的样子:

foreach (Player teamPlayer in team.Players)
{
    bool allGamePlayersInRange = game.Allies.Players.All(g => 
        (Math.Abs(teamPlayer.Skill - g.Skill) <= 200);

    // Check if the player in the team is in skill range of the game he wants to join. If yes increase the counter.
    if (allGamePlayersInRange)
        teamPlayersInSkillRange++;

}

现在这个循环看起来可以重构为一个Count()调用。但是,如果我们仔细检查它之后的代码,我们会发现它与我们刚刚重构的循环完全相同,这意味着我们可以直接将其重构为All()调用,从而完成重构。

于 2012-12-21T23:59:25.153 回答
0

试试这个:

foreach(Team team in match.TeamsInQueue)
{
    if(team.Players.Insersect(match
           .SelectMany(m => m.AvailableGames, g=> g.Allies.Players), 
            new PlayerSkillComparer().Count() == team.Players.Count()) {
         // ToDO: Implement join process here.
    }
}

如果两个给定对象的技能差异 <= 200,则PlayerSkillComparerimplementsIEqualityComparer<Player>及其Equals方法返回 true 。请参见此处Player的示例。

于 2012-12-21T23:14:29.207 回答