【问题标题】:Sorting lists by multiple variables in C# (Unity)在 C# (Unity) 中按多个变量对列表进行排序
【发布时间】:2020-06-13 20:25:34
【问题描述】:

我是编程新手,正在使用 Unity 将我和朋友一起玩的棋盘游戏转换为虚拟版本。游戏有一种独特的方式来确定每一轮后的回合顺序,我真的很困惑如何实现它。我将每个玩家的数据保存在一个名为“Player”的脚本实例中,并有两个函数来检索相关变量(GetUnits() 和 GetScore())。

我还在玩家列表“playerList”中保留了所有玩家的列表。可以有 3-6 名玩家。

每轮的回合顺序是单位数量最少的玩家(上升),如果两个玩家并列,则得分较高的玩家(下降)。如果仍然并列,玩家将不得不为第三次决胜局掷骰子。我需要在开始下一轮之前获取完整的回合顺序(我无法重新计算,因为每个玩家都轮到他们。)

实际上几乎不需要第三次决胜局,第二轮之后也很少需要第二次决胜局。所有这一切的例外当然是游戏的第一轮,每个人都在分数和单位上打成平手。我可以只为 Rd 1 编写一个单独的 die-roller 函数,但如果我正确地编写了我的 setTurn 函数,它应该可以无缝地处理 Rd 1 以及任何其他转弯的所有其他可能的平局场景。

每次我坐下来编写代码时,都会遇到大量嵌套循环和 if 语句,我无法完全找到解决方案。非常感谢任何有关如何解决此问题的建议。

【问题讨论】:

  • 有什么要添加的代码吗?

标签: c# sorting unity3d


【解决方案1】:

为您的 Player 类实现 IComparable。然后你可以简单地将你的列表告诉Sort() 本身,你就完成了。

实现接口看起来像这样:

public class Player : IComparable<Player>
{

    private static Random R = new Random();

    public String Name;
    public int GetUnits() { return -1; } // obviously you have other code to support this
    public int GetScore() { return -1; } // obviously you have other code to support this

    public int CompareTo(Player other)
    {
        // sort by Units first
        int result = this.GetUnits().CompareTo(other.GetUnits());
        if (result == 0) // units were equal
        {
            // sort by score next
            result = this.GetScore().CompareTo(other.GetScore());
            if (result == 0) //scores were equal
            {
                // sort by dice roll: <=3 first player, otherwise second player
                result = (R.Next(1, 7) <= 3 ? -1 : 1);
            }
        }
        return result;
    }

}

然后您只需将列表告诉Sort() 本身!

playerList.Sort();

来自另一个答案的原始海报评论:

我唯一关心的是当有 3 种(或更多)平局时会发生什么?一世 会希望 3 名玩家同时互相滚动并且 不是 1 对 1 卷。例如,在第一轮之前(假设 6 玩家)我想做一个 6 路掷骰子。

这实际上比你想象的要困难。考虑我们首先在没有掷骰子的情况下进行排序。然后,您必须遍历结果并查看您的排序中哪些可能的 MULTIPLE 部分有平局。然后你必须为每个打平的玩家掷骰子。之后,您必须仅对已排序列表中的子集进行排序(将所有其他玩家留在当前位置)以仅重新排列并列的子部分。请记住,这可能发生在您列表的多个位置。还有一种可能性是,在掷骰子后,可能会有更多的平局需要更多的通行证。 Sort() 的重载允许您仅对列表的一部分进行排序。

因此,您将对 (1) 单位/分数、(2) 检查平局、(3) 掷骰子、(4) 对所有平局的子集进行排序,循环回到 (2) 的次数为必要的。

【讨论】:

    【解决方案2】:

    这是一个您可以考虑的简单解决方案。

    如果我正确理解了您的规则,您希望先按最低分对玩家进行排序,然后对于决胜局 1 名得分更高的玩家先行,然后如果仍然平局,则它只是 rng(掷骰子)。

    您可以使用 c# IComparer 来做到这一点。它比听起来简单:

     public class PlayerCompare : IComparer<Player>
    {
        public int Compare(Player x, Player y)
        {
            int unitComparison = x.Units.CompareTo(y.Units);//Note im comparing X to Y here so its ascending order.
    
            if (unitComparison != 0)
            {
                //if they have not the same number of unit, return the higher one.
                return unitComparison;
            }
            else
            {
                //if they have the same number of units, compare the scores
                int scoreComparison = y.Score.CompareTo(x.Score);//Note im comparing Y to X here so its descending order.
                if (scoreComparison != 0)
                {
                    //If they don't have the same number of units, return the lower one.
                    return scoreComparison;
                }
                else 
                {
                    //They have the same number of units and score, roll a dice.
                    if (UnityEngine.Random.value > 0.5f)//this is a straight up 50/50
                    {
                        return 1;
                    }
                    else
                    {
                        return -1;
                    }
                }
            }
        }
    }
    public class Player 
    {
        public int Units;
        public int Score;
    
        public Player(int units, int score) 
        {
            Units = units;
            Score = score;
        }
    }
    //This is an example list of players (6) with assorted scores/units
    public List<Player> playerList = new List<Player>() { 
        new Player(1,10), new Player(8, 2), 
        new Player(2, 20), new Player(4, 0), 
        new Player(1, 10), new Player(8, 20) 
    };
    //This is the sorting
    private void Sort() 
    {
        playerList.Sort(new PlayerCompare());
    }
    

    现在您只需要更新分数/单位并在回合结束时调用 Sort()。我为示例制作了一个虚拟玩家类,显然使用你的。

    【讨论】:

    • 谢谢你——这对理解如何实现 IComparer 很有帮助。我唯一担心的是当有 3 个(或更多)方式的领带时会发生什么?我希望这 3 名玩家同时互相对抗,而不是一对一。例如,在第一轮之前(假设有 6 名玩家),我想做一个 6 路掷骰子。
    猜你喜欢
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多