简要说明:从数组中随机选择两个项目,然后从数组中删除它们,然后从两个已经随机选择的项目中随机选择一个项目。
我知道以前可能有人问过这个问题,但我能找到的所有答案我都不知道如何应用于我的代码。
这是我的代码:
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 队),从这两支球队中随机选择,这样我就可以决定获胜者。我已经尝试了很多方法,但都没有奏效,我主要需要帮助解决第一个问题,但如果有人也能帮助解决第二个问题,我们将不胜感激。
答案 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
集合;)
因此,通过简单地随机化原始引用的地址列表,我们可以使用确定性逻辑实现随机输出。