9

この小さなラウンド ロビンプロジェクトを達成するのに苦労しています。私がやろうとしているのは、ゲームのプレビューカレンダーを生成することです

次に、出力したい。

1 日目: チーム 1 対チーム 2。チーム 3 対 チーム 4。チーム 5 対 チーム 6。

2 日目 チーム 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++;
            }

        }
    }

EDIT:Javaでコードサンプルを見つけましたが、翻訳できません...

4

8 に答える 8

13

これは、剰余算術を使用して簡単に実行できるはずです。

更新 2: (約束された正しいアルゴリズム)

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]);
        }
    }
}

毎日のチームの試合を出力します。

アルゴリズムがどのように機能するかを簡単に説明してみましょう。

最初のチームを除くすべてのチームをローテーションしているので、最初のチームを除くすべてのチームを配列に入れると、その日に基づくインデックスオフセットを使用してその配列から最初のチームを読み取るだけでよいことに気付きました。モジュラー演算を正しくラップアラウンドします。実際には、その配列を両方向に無限に繰り返すものとして扱い、ビューを徐々に右 (または左) にスライドさせます。

ただし、問題が 1 つあります。それは、これが正しく機能するために、チームを特定の方法で順序付けする必要があるという事実です。そうしないと、正しい回転が得られません。このため、一致する 2 番目のチームも非常に独特な方法で読み取る必要があります。

リストを準備する正しい方法は次のとおりです。

  • 最初のチーム (Team#1) をリストに入れないでください。
  • チームリストの後半を取り、リストの先頭に置きます。
  • リストの前半を取り、それを逆にしてリストに入れます (ただし、Team#1 は除きます)。

さて、リストから読み取る正しい方法は次のとおりです。

  • 毎日、見ている最初のインデックスを ずつ増やします1
  • その場所で最初に表示されるチームについては、そのチームを Team#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.
于 2009-08-18T10:59:54.610 に答える
6

ラウンドロビン トーナメントをスケジュールしたいようですね。wpの記事にはアルゴリズムが含まれています。

配列を回転させようとしている場所さえわかりません。順列は次のようになります: 1 -> 2 -> 3 -> 4 ... -> n/2 - 1 -> n - 1 -> n - 2 -> n - 3 -> ... -> n /2 -> 1 (0 は固定のまま)。2 つのループ (上段と下段) でそれを行うことができます。

于 2009-08-17T16:04:54.710 に答える
2

ダブルラウンドロビンスケジュールを計算する回答済みコードブロックを改善しました

GameEntities db = new GameEntities();


private void btnTeamFixtures_Click(object sender, RoutedEventArgs e)
    {
        txtResults.Text = null;

        var allTeams = db.Team.Select(t => t.TeamName);

        int numDays = allTeams.Count() - 1;
        int halfsize = allTeams.Count() / 2;

        List<string> temp = new List<string>();
        List<string> teams = new List<string>();

        teams.AddRange(allTeams);
        temp.AddRange(allTeams);
        teams.RemoveAt(0);

        int teamSize = teams.Count;

        for (int day = 0; day < numDays * 2; day++)
        {
            //Calculate1stRound(day);
            if (day % 2 == 0)
            {
                txtResults.Text += String.Format("\n\nDay {0}\n", (day + 1));

                int teamIdx = day % teamSize;

                txtResults.Text += String.Format("{0} vs {1}\n", teams[teamIdx], temp[0]);

                for (int idx = 0; idx < halfsize; idx++)
                {
                    int firstTeam = (day + idx) % teamSize;
                    int secondTeam = ((day + teamSize) - idx) % teamSize;

                    if (firstTeam != secondTeam)
                    {
                        txtResults.Text += String.Format("{0} vs {1}\n", teams[firstTeam], teams[secondTeam]);
                    }
                }
            }

            //Calculate2ndRound(day);
            if (day % 2 != 0)
            {
                int teamIdx = day % teamSize;

                txtResults.Text += String.Format("\n\nDay {0}\n", (day + 1));

                txtResults.Text += String.Format("{0} vs {1}\n", temp[0], teams[teamIdx]);

                for (int idx = 0; idx < halfsize; idx++)
                {
                    int firstTeam = (day + idx) % teamSize;
                    int secondTeam = ((day + teamSize) - idx) % teamSize;

                    if (firstTeam != secondTeam)
                    {
                        txtResults.Text += String.Format("{0} vs {1}\n", teams[secondTeam], teams[firstTeam]);
                    }
                }
            }
        }
    }

必要に応じて、2 つのメソッドを作成し、2 つのコメント行で行ったように pass と integer(Day) を作成して、コードを分離できます。

ご質問やご提案がありましたら、お気軽に返信してください。

于 2011-09-14T19:55:00.543 に答える
1

複雑な方法かもしれませんが、これはグラフ理論の問題に還元できます。チームごとにグラフの頂点を作成し、すべての頂点間にエッジを作成します (完全なグラフになります)。次に、アルゴリズムについて:

毎日 i = 1 .. n :

  • 直接接続されているマークされていない任意の 2 つの頂点を選択し、それらの間のエッジに i のラベルを付けます。両方の頂点をマークします。
  • すべての頂点がマークされるまで繰り返します。
  • ラベル付けされたエッジを出力します (つまり、チーム 1 とチーム 2、チーム 3 とチーム 4 など)
  • グラフからラベル付きエッジを削除し、すべての頂点をマークなしにリセットします。
于 2009-08-18T11:26:40.700 に答える
1

実装を github RoundRobinTournamentScheduleに投稿しました。 対応する nuget パッケージを見つけて、独自のソリューションで使用できます。

乾杯

于 2020-02-14T17:32:52.907 に答える
0

希望する日ごとに可能な組み合わせを計算してみてはいかがでしょうか。

  1. 各ペア内でそれらを並べ替えます。つまり、最小番号のチームが常にどのペアでも最初になります。
  2. リストされた各日の組み合わせを、各組み合わせの最初の順に並べ替えます。
于 2009-08-18T10:49:16.830 に答える