我在实现这个小 round robin 时遇到了一些麻烦项目。我尝试做的是生成游戏预览日历
然后我要输出;
第 1 天: 第 1 队对第 2 队; 第 3 队对第 4 队; 第 5 队对第 6 队;
第二天 第 1 队对第 4 队; 第 6 队对第 3 队; 第 2 队对第 5 队;
直到锦标赛结束;
这是我到目前为止得到的代码,但我很难让第一支球队固定而阵列的其余部分轮换......:
static void Main(string[] args)
{
string[] ListTeam = new string[] {"Equipe1", "Equipe2", "Equipe3", "Equipe4", "Equipe5", "Equipe6"};
IList<Match> ListMatch = new List<Match>();
it NumberOfDays = (ListTeam.Count()-1);
int y = 2;
for (int i = 1; i <= NumberOfDays; i++)
{
Console.WriteLine("\nDay {0} : \n",i);
Console.WriteLine(ListTeam[0].ToString() + " VS " + ListTeam[i].ToString());
for (y =ListTeam.Count(); y>0 ; y--)
{
Console.WriteLine(ListTeam[y].ToString() + " VS " + ListTeam[y+1].ToString());
y++;
}
}
}
编辑:我找到了一个 code sample in java but我不会翻译...
最佳答案
这应该很容易使用模块化算法来完成:
更新 2:(如 promise 的正确算法)
public void ListMatches(List<string> ListTeam)
{
if (ListTeam.Count % 2 != 0)
{
ListTeam.Add("Bye");
}
int numDays = (numTeams - 1);
int halfSize = numTeams / 2;
List<string> teams = new List<string>();
teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());
int teamsSize = teams.Count;
for (int day = 0; day < numDays; day++)
{
Console.WriteLine("Day {0}", (day + 1));
int teamIdx = day % teamsSize;
Console.WriteLine("{0} vs {1}", teams[teamIdx], ListTeam[0]);
for (int idx = 1; idx < halfSize; idx++)
{
int firstTeam = (day + idx) % teamsSize;
int secondTeam = (day + teamsSize - idx) % teamsSize;
Console.WriteLine("{0} vs {1}", teams[firstTeam], teams[secondTeam]);
}
}
}
这将打印每天的团队比赛。
让我快速解释一下该算法的工作原理:
我注意到,由于我们正在轮换除第一个团队之外的所有团队,如果我们将除第一个团队之外的所有团队都放在一个数组中,那么我们应该使用基于一天并进行模块化运算以正确环绕。在实践中,我们会将该数组视为在两个方向上无限重复,并且我们会将我们的 View 逐渐向右(或向左)滑动。
然而,有一个障碍,那就是我们必须以一种非常特殊的方式对团队进行排序才能使其正常工作。否则,我们无法获得正确的旋转。因此,我们也需要以一种非常特殊的方式阅读匹配的第二支球队。
准备列表的正确方法如下:
- 永远不要将第一个团队(Team#1)放在列表中。
- 将团队列表的后半部分放在列表的前面。
- 取列表的前半部分,将其反转并将它们放入列表中(但不是 Team#1)。
现在,正确的读出列表的方法如下:
- 对于每一天,将您查看的第一个索引增加
1
。 - 对于您在该位置看到的第一支球队,将该球队与第一支球队相匹配。
- 对于列表中的下一支球队 (
(day + idx) % numDays
),我们通常会将其与偏移一半球队数量减 1 的球队相匹配(减 1 因为我们自己处理了第一场比赛)。但是,由于列表的后半部分是通过还原准备的,因此我们需要在列表的还原后半部分中匹配该偏移量。一种更简单的方法是观察,这相当于匹配相同的索引,但从列表的末尾开始。给定当前day
偏移量为(day + (numDays - idx)) % numDays
。
更新 3: 我对我的解决方案涉及如此复杂的数组元素选择、匹配和反转感到不高兴。在考虑我的解决方案涉及的内容后,我意识到我太在意保持团队的秩序了。但是,这不是必需的,并且可以通过不关心初始顺序来获得不同但同样有效的时间表。重要的是我在解释的第二部分中描述的选择算法。
因此您可以简化以下几行:
teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());
到:
teams.AddRange(ListTeam); // Copy all the elements.
teams.RemoveAt(0); // To exclude the first team.
关于c# - C#中的循环赛算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1293058/