2009-08-18 16 views
6

Mam problem z uzyskaniem tego małego projektu round robin. Co staram się zrobić, to wygenerować kalendarz podglądu gierAlgorytm turnieju Round Robin w języku C#

następnie chcę wydrukować;

dzień 1: Team 1 vs Team 2; Team 3 vs Team 4; Zespół 5vs Team 6;

dzień 2 Team 1 vs Team 4; Team 6 vs Team 3; Drużyna 2 vs Drużyna 5;

do końca mistrzostw;

Oto kod mam tak daleko, ale mam problemy, aby pozwolić pierwszy zespół stały, podczas gdy reszta tablicy obraca ...:

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: Znalazłem code sample in java but Nie mogę przetłumaczyć ...

+0

Nie mogę znaleźć sposobu na załapanie pierwszego zespołu i nadal nie stosuję innych meczów. – Polo

+0

@John Nolan: Przepraszam za literówki i pisownię ... – Polo

+0

Implementacja Java, z którą się łączyłeś, jest bardzo niejasna. Również fakt, że tekst i zmienne są w języku francuskim, nie pomaga (przynajmniej ja). – paracycle

Odpowiedz

11

To powinno być dość łatwe do zrobienia przy użyciu arytmetyki modularnej:

UPDATE 2: (Jak obiecał poprawny algorytm)

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

które wydrukować każdy dzień mecze zespołu.

Pozwól mi szybko starają się wyjaśnić, jak działa algorytm:

Zauważyłem, że skoro jesteśmy obracając wszystkie zespoły z wyjątkiem pierwszego, jeśli stawiamy wszystkie zespoły w tablicy z wyjątkiem pierwszego, potem powinien po prostu odczytać pierwszy zespół z tej tablicy, używając przesunięcia indeksu opartego na danym dniu i wykonując modularną arytmetykę, aby poprawnie owijać. W praktyce traktowalibyśmy tę tablicę jako nieskończenie powtarzającą się w obu kierunkach, a my przesuwalibyśmy nasz widok stopniowo w prawo (lub w lewo).

Istnieje jednak jeden szkopuł, i to jest fakt, że musimy bardzo dokładnie zamówić zespoły, aby działały poprawnie. W przeciwnym razie nie otrzymamy prawidłowego obrotu. Z tego powodu musimy również czytać pasujący drugi zespół w bardzo osobliwy sposób.

Prawidłowy sposób na przygotowanie listy jest następujący:

  • Nigdy umieścić pierwszego zespołu (Team # 1) na liście.
  • Weź ostatnią połowę listy zespołów i umieść je na początku listy.
  • Zrób pierwszą połowę listy, cofnij i umieść je na liście (ale nie w zespole nr 1).

Teraz poprawny sposób odczytać z listy jest następująca:

  • Dla każdego dnia, przyrost pierwszy indeks patrzysz przez 1.
  • Dla pierwszego zespołu, który widzisz w tej lokalizacji, dopasuj tę drużynę do Drużyny nr 1.
  • Dla następnej drużyny na liście ((day + idx) % numDays), normalnie dopasowalibyśmy ją do drużyny, która jest zrekompensowana o połowę liczbą drużyn minus 1 (minus 1, ponieważ sami poradziliśmy sobie z pierwszym meczem). Ponieważ jednak druga połowa naszej listy została przygotowana przez cofnięcie, musimy dopasować to przesunięcie w odwróconej drugiej połowie listy. Prostszym sposobem jest stwierdzenie, że jest to równoważne dopasowaniu tego samego indeksu, ale od końca listy. Biorąc pod uwagę aktualne przesunięcie day, czyli (day + (numDays - idx)) % numDays.

UPDATE 3: nie był zadowolony, że moje rozwiązanie udział takiego zwichrowanych wybór, dopasowywanie odwracania elementów macierzy. Po tym, jak zastanowiłem się nad tym, w czym znalazło się moje rozwiązanie, zdałem sobie sprawę z tego, że byłem zbyt roztropny, aby utrzymać porządek w drużynach, tak jak podałem. Jednak nie jest to wymagane i można uzyskać inny, ale równie ważny harmonogram, nie dbając o początkowe zamówienie. Liczy się jedynie algorytm doboru, który opisuję w drugiej części mojego wyjaśnienia.

W ten sposób można uprościć następujące linie:

teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize)); 
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse()); 

do:

teams.AddRange(ListTeam); // Copy all the elements. 
teams.RemoveAt(0); // To exclude the first team. 
+0

Jak dotąd tak dobrze, ale jeśli spróbujesz ouput Team 1 vs Team 2 otrzymasz wyjątek – Polo

+0

Widzę, ale nie mogę tego zrobić za pomocą dwóch pętli, aby uzyskać A vs B, C vs D .... – Polo

+0

Proszę . Zaktualizowałem to. – paracycle

6

Wygląda na to, że chcesz zaplanować round-robin tournament. Artykuł wp zawiera algorytm.

Nie widzę, gdzie próbujesz nawet obrócić tablicę. Permutacja będzie wyglądała mniej więcej tak: 1 -> 2 -> 3 -> 4 ... -> n/2 - 1 -> n - 1 -> n - 2 -> n - 3 -> ... -> n/2 -> 1 (i 0 pozostaje stałe). Możesz to zrobić w 2 pętlach (górny i dolny wiersz).

+0

Dziękuję za odpowiedź, ale czy istnieje sposób, aby ją wygenerować losowo? – Polo

+0

gdzie? mogłem tylko znaleźć metode – Polo

+0

? Metoda powinna prowadzić bezpośrednio do odpowiedniego algorytmu. Dodanie losowego oznaczania drużyn jest banalnym dodatkiem i spełnia twoje wymagania. Można zauważyć, że "obrót w prawo" na stronie WP mówi o pierścieniu, więc 1 2 3 4, obrócony zgodnie z ruchem wskazówek zegara to 4 1 2 3. – nlucaroni

0

Jak o obliczenia możliwych kombinacji dla każdego dnia, które chcesz potem

  1. sortować je w każdej parze tj najniższym numerze zespół jest zawsze pierwszy w dowolnej pary.
  2. sortuj listę parowania dla każdego dnia przez pierwszą w każdej parze .
+0

(NumberOfTeams/2) i po? Nie rozumiem, ale muszę założyć pierwszy zespół i obrócić tablicę, dopóki nie wróci do pierwszego węzła, ale nie mogę znaleźć sposobu. – Polo

+0

Mam ochotę zakodować pierwszy zespół, a następnie obrócić tablica (część tęsknię), aż wraca do oryginalnego punktu – Polo

+0

Myślę, że próbuję powiedzieć, zamiast próbować zrobić rotację * i * utrzymać zespół1 najpierw za pomocą algorytmu jednoprzebiegowego zrobić to w dwuprzebiegowym zamiast tego algorytm. – RobS

1

może to być metoda zwinięty, jednak może być zmniejszona do problemu teorii wykresu. Utwórz wierzchołek wykresu dla każdej drużyny i utwórz krawędź między każdym wierzchołkiem (tak, aby był to kompletny wykres). Następnie algorytmu:

Dla każdego dnia, w którym n = 1 ..:

  • wybrać dowolną z dwóch nieoznaczonych wierzchołków, które są bezpośrednio związane i etykietę krawędzi między nimi i. Zaznacz oba wierzchołki.
  • Powtarzaj aż do zaznaczenia wszystkich wierzchołków.
  • Służy do wyprowadzania oznaczonych krawędzi (np. Team1 vs team2, team3 vs team4 etc)
  • Usuń oznaczone krawędzie z wykresu i zresetuj wszystkie wierzchołki, aby usunąć zaznaczenie.
+0

To trochę do myślenia, zaczynam – Polo

+0

Uczciwa. To raczej teoretyczne niż praktyczne rozwiązanie. – tw39124

2

były wprowadzane ulepszenia w odpowiadał bloku kodu, który oblicza podwójny rozkład okrężny

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

Jeśli u u można utworzyć 2 metod i przejść i całkowitą (dzień), jak i nie w 2 skomentowane linie, aby oddzielić kod.

Jeśli masz jakieś pytania lub sugestie, odpowiedz.

Powiązane problemy