配对:随机选择两支球队并随机选择获胜者

时间:2021-05-31 17:37:01

标签: c# random duplicates

简要说明:从数组中随机选择两个项目,然后从数组中删除它们,然后从两个已经随机选择的项目中随机选择一个项目。

我知道以前可能有人问过这个问题,但我能找到的所有答案我都不知道如何应用于我的代码。

这是我的代码:

string[] teams = { "Team 1", "Team 2", "Team 3", "Team 4", "Team 5", "Team 6",
    "Team 7", "Team 8" };

Console.WriteLine("The available teams are: ");
for (int i = 0; i < teams.Length; i++)
{
    Console.WriteLine(teams[i]);
}

Random rnd1 = new Random();
int r1 = rnd1.Next(teams.Length);
Random rnd2 = new Random();
int r2 = rnd2.Next(teams.Length);
Console.WriteLine("Round 1: " + teams[r1] + " vs " + teams[r2]);

我怎样才能做到让两支球队总是不同的,这样我就可以进行第二轮比赛,而这将是另外两支不同的球队?

我需要做的另一件事是,当两支球队被选中参加一轮比赛时(假设是第 3 队和第 7 队),从这两支球队中随机选择,这样我就可以决定获胜者。我已经尝试了很多方法,但都没有奏效,我主要需要帮助解决第一个问题,但如果有人也能帮助解决第二个问题,我们将不胜感激。

2 个答案:

答案 0 :(得分:0)

为了实施它,我们确实需要跟踪团队已经进入的回合。

8 支球队最多可以进行 3 轮比赛。

在做任何事情之前,我们可以洗牌我们的团队名单,然后将他们配对以玩他们的游戏。获胜队伍将晋级下一轮。

首先要定义我们的班级团队:

public class Team
{
    public string Name { get; set; }
    public int Round { get; set; }
}

然后我们要做的是创建两个嵌套循环。

外循环模拟正在进行的回合 - 而内循环模拟两支球队之间的当前比赛,决定获胜者。

综合起来,我们有:

public class Team
{
    public string Name { get; set; }
    public int Round { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        List<Team> teams = new List<Team>
        {
            new Team
            {
                Name = "Team 1",
                Round = 0
            },
            new Team
            {
                Name = "Team 2",
                Round = 0
            },
            new Team
            {
                Name = "Team 3",
                Round = 0
            },
            new Team
            {
                Name = "Team 4",
                Round = 0
            },
            new Team
            {
                Name = "Team 5",
                Round = 0
            },
            new Team
            {
                Name = "Team 6",
                Round = 0
            },
            new Team
            {
                Name = "Team 7",
                Round = 0
            },
            new Team
            {
                Name = "Team 8",
                Round = 0
            }
        };

        for (int j = 0; j < teams.Count / (teams.Count / 4); j++)
        {
            //select current round and shuffles the teams
            Random rng = new Random();
            var currentPlayingTeams = teams.Where(x => x.Round == j).Select(c => c).ToList().OrderBy(x => rng.Next()).ToList();

            if (currentPlayingTeams.Count > 1)
            {
                Console.WriteLine($"---------------- Round {j + 1}----------------------");

                for (int i = 0; i < currentPlayingTeams.Count; i += 2)
                {
                    var currentMatch = currentPlayingTeams.GetRange(i, 2);

                    Console.WriteLine($"{currentMatch[0].Name} VS {currentMatch[1].Name}");
                    System.Threading.Thread.Sleep(1000);

                    Random ran = new Random();
                    var matchWinner = ran.Next(0, 2);

                    Console.WriteLine($"{currentMatch[matchWinner].Name} Won");
                    System.Threading.Thread.Sleep(1000);

                    teams.FirstOrDefault(x => x.Name == currentMatch[matchWinner].Name).Round++;
                }
            }
        }

        var winner = teams.OrderByDescending(v => v.Round).First();
        Console.WriteLine("---------------- Result----------------------");
        Console.WriteLine($"The winning team is {winner.Name}");
        Console.ReadLine();
    }
}

因为我们已经洗牌了 - 我们可以选择前两个让他们玩。

该实现要求团队数量为 2n 的幂(4、8、16、32 等)。

答案 1 :(得分:0)

一种方法是创建数组的副本,把它想象成你把每个名字放在一张纸上,然后把它们放在帽子里,我们称之为pool。现在,当您从 pool 中随机选择一个团队时,请在再次选择之前将该团队从 pool 中删除:

Random rand = new Random();
string[] teams = { "Team 1", "Team 2", "Team 3", "Team 4", "Team 5", "Team 6", "Team 7", "Team 8" };
Console.WriteLine("The available teams are: ");
for (int i = 0; i < teams.Length; i++)
{
    Console.WriteLine(teams[i]);
}

List<int> pool = new List<int>(Enumerable.Range(0, teams.Length));
int round = 0;
while(pool.Any())
{
    round++;
    int index = rand.Next(0, pool.Count);
    int r1 = pool[index];
    pool.RemoveAt(index);

    index = rand.Next(0, pool.Count);
    int r2 = pool[index];
    pool.RemoveAt(index);

    Console.Write($"Round {round}: {teams[r1]} vs {teams[r2]}");
    int winner = rand.Next(0, 2) == 1 ? r1 : r2;
    Console.WriteLine($" - Winner: {teams[winner]}");
}
<块引用>

如评论中所述,无需创建新的 Random 实例,只需重用现有实例即可。

我不是这种语法的忠实粉丝,当使用对象引用而不是将索引数组保存到另一个数组中时,这样的逻辑通常更容易理解,但是这非常接近 OP 问题。

执行此操作具有以下输出:

The available teams are:
Team 1
Team 2
Team 3
Team 4
Team 5
Team 6
Team 7
Team 8
Round 1: Team 5 vs Team 4 - Winner: Team 4
Round 2: Team 6 vs Team 1 - Winner: Team 6
Round 3: Team 3 vs Team 2 - Winner: Team 3
Round 4: Team 8 vs Team 7 - Winner: Team 8

从帽子里拔出名字的场景中,我们通常做的就是把名字放在帽子里,把它们洗干净,然后我们依次把它们抽出来。所以我们实际上可以通过对 pool 进行排序而不是删除随机索引处的项目来稍微简化逻辑,一旦集合排序一次,结果就已经随机足够了。< /p>

List<int> pool = new List<int>(Enumerable.Range(0, teams.Length).OrderBy(x => rand.Next()));
int round = 0;
while (pool.Any())
{
    round++;
    int r1 = pool[0];
    int r2 = pool[1];
    // remove the entries before the next round
    pool.RemoveAt(0);
    pool.RemoveAt(0); // previous remove has shifted the array

    Console.Write($"Round {round}: {teams[r1]} vs {teams[r2]}");
    // still randomly select a winner from the two selected
    int winner = rand.Next(0, 2) == 1 ? r1 : r2;
    Console.WriteLine($" - Winner: {teams[winner]}");
}

这是一个细微的区别,但是随机排序数组可以让你写出更多的确定性代码,而且更可预测的代码更容易调试,结果仍然是随机的,实际上现在我们不必从池中删除项目,我们可以简单地枚举池数组:

int [] pool = Enumerable.Range(0, teams.Length).OrderBy(x => rand.Next()).ToArray();
for (int index = 0, round = 1; index < pool.Length; index += 2, round ++)
{
    int r1 = pool[index];
    int r2 = pool[index + 1];

    Console.Write($"Round {round}: {teams[r1]} vs {teams[r2]}");
    // still randomly select a winner from the two selected
    int winner = rand.Next(0, 2) == 1 ? r1 : r2;
    Console.WriteLine($" - Winner: {teams[winner]}");
}

如果输入的团队可能是一个奇数,这可能发生,只需在那里打个勾并给最后一个团队再见

var t = teams.ToList();
t.Add("Team 9");
teams = t.ToArray();
// now that there is an odd number of teams...
int[] p = Enumerable.Range(0, teams.Length).OrderBy(x => rand.Next()).ToArray();
for (int index = 0, round = 1; index < p.Length; index += 2, round ++)
{
    if (p.Length > index + 1)
    {
        int r1 = p[index];
        int r2 = p[index + 1];

        Console.Write($"Round {round}: {teams[r1]} vs {teams[r2]}");
        // still randomly select a winner from the two selected
        int winner = rand.Next(0, 2) == 1 ? r1 : r2;
        Console.WriteLine($" - Winner: {teams[winner]}");
    }
    else
    {
        int rb = p[index];
        Console.Write($"Round {round}: {teams[rb]} *** bye ***");
    }
}

上面的输出是:

Round 1: Team 4 vs Team 2 - Winner: Team 4
Round 2: Team 5 vs Team 3 - Winner: Team 3
Round 3: Team 8 vs Team 1 - Winner: Team 1
Round 4: team 9 vs Team 6 - Winner: team 9
Round 5: Team 7 *** bye ***

对于之前的执行,pool 具有以下内容:

[4,2,5,3,8,1,9,6,7]

除了添加第 9 个之外,我们不需要操作原始的 teams 集合;) 因此,通过简单地随机化原始引用的地址列表,我们可以使用确定性逻辑实现随机输出。