Mega Code Archive

 
Categories / Delphi / Examples
 

How To Create A Round Robin Tournament Schedule

Title: How To Create A Round Robin Tournament Schedule Question: How do I create a balanced round robin tournament schedule which ensures that every team plays every other team once with the minimum amount of idle time (a/k/a byes) and ensures that teams have an equal number of home and away games. Answer: The creation of a balanced round robin schedule is more complex than it first appears. There are several delphi round-robin components that are available on the web ... for example the one from engerning objects international at http://www.engineeringobjects.com/RndRobin.htm which costs $495.00. I wrote this algorithm to quickly and cheaply calculate a round robin schedule. Currently, the program has a hard-coded maximum number of 500 teams; however, this can easily be increased. If you have no need for such an algorithm then so be it, but I hope that anyone who needs to create such a schedule will give this algorithm a try. The CreateRoundRobin procedure will easily create a schedule for you. For example assume that there are 5 teams, a valid schedule would be. Round 1 Home : 1 Away: 4 Home : 2 Away: 3 Home : 5 Away: -1 Round 2 Home : 5 Away: 3 Home : 1 Away: 2 Home : 4 Away: -1 Round 3 Home : 4 Away: 2 Home : 5 Away: 1 Home : 3 Away: -1 Round 4 Home : 3 Away: 1 Home : 4 Away: 5 Home : 2 Away: -1 Round 5 Home : 2 Away: 5 Home : 3 Away: 4 Home : 1 Away: -1 Most traditional round robin schedules look like the following, but there is no easy way to calculate which team is the home team (or has the home field) and which team is away team (or plays on the away field). team \ 1 2 3 4 5 6 7 8 9 10 round \............................................................ 1: 10 9 8 7 6 5 4 3 2 1 2: 6 10 9 8 7 1 5 4 3 2 3: 2 1 10 9 8 7 6 5 4 3 4: 7 3 2 10 9 8 1 6 5 4 5: 3 4 1 2 10 9 8 7 6 5 6: 8 5 4 3 2 10 9 1 7 6 7: 4 6 5 1 3 2 10 9 8 7 8: 9 7 6 5 4 3 2 10 1 8 9: 5 8 7 6 1 4 3 2 10 9 Instead of creating a tratitional [N by N] array, I have created an [N by 1/2 N by 2] array to keep track of the home and away aspects of the round robin tournament. const MaxTeams = 500; MaxRounds = MaxTeams; MaxGames = (MaxTeams+1) Div 2; Home = 1; Away = 2; Bye : Integer = -1; type TGameAry = Array[1..MaxTeams] of Integer; TRoundRobinAry = Array[1..MaxRounds,1..MaxGames,Home..Away] of Integer; .... procedure TForm1.CreateRoundRobin(var RoundRobinAry: TRoundRobinAry; const Teams: Integer); var GameAry : TGameAry; Half, Rounds, Bottom, SwitchBottom, TempGameValue, i, ii, iii : Integer; begin For i := 1 to MaxRounds do For ii := 1 to MaxGames do For iii := 1 to 2 do RoundRobinAry[i][ii][iii] := 0; IF ((Teams MaxTeams)) Then exit; //Initilize Team Array with Team Numbers For i := 1 to Teams do GameAry[i] := i; if (Teams then For i := (Teams+1) to MaxTeams do GameAry[i] := 0; Half := (Teams-1) Div 2; IF ((Teams Mod 2)=0) Then Begin Rounds := Teams - 1; Bottom := Teams - 2; SwitchBottom := Bottom + 1; End else Begin Rounds := Teams; Bottom := Teams - 1; SwitchBottom := Teams; end; for i := 1 to Rounds do begin for ii := 1 to Half do begin RoundRobinAry[i][ii][Home] := GameAry[ii]; RoundRobinAry[i][ii][Away] := GameAry[Bottom-ii+1]; end; If ((Teams - Bottom) = 2) // if even number of teams then begin if i mod 2 = 0 then begin RoundRobinAry[i][Half+1][Home] := GameAry[SwitchBottom]; RoundRobinAry[i][Half+1][Away] := GameAry[Bottom+2]; end else begin RoundRobinAry[i][Half+1][Away] := GameAry[SwitchBottom]; RoundRobinAry[i][Half+1][Home] := GameAry[Bottom+2]; end end else begin // if odd number of teams then idle team gets a bye RoundRobinAry[i][Half+1][Home] := GameAry[SwitchBottom]; RoundRobinAry[i][Half+1][Away] := Bye; end; //rotate value of gameary TempGameValue := GameAry[SwitchBottom]; for ii := SwitchBottom downto 2 do GameAry[ii] := GameAry[ii-1]; GameAry[1] := TempGameValue; end; end; You can easily print the result to a richedit with a push of a button. procedure TForm1.Button1Click(Sender: TObject); const NoOfTeams : integer = 7; var roundrobinary : TRoundRobinAry; begin RichEdit1.Clear; CreateRoundRobin(RoundRobinAry,NoOfTeams); PrintFullChart(RoundRobinAry); //see below end; Procedure Tform1.PrintFullChart(const RoundRobinAry: TRoundRobinAry;); var i,ii : integer; begin richedit1.Lines.BeginUpdate; i := 1; ii := 1; repeat; Richedit1.Lines.Add(Format('Round : %d', [i])); while (RoundRobinAry[i][ii][Home] 0) do begin if RoundRobinAry[i][ii][away] - 1 then Richedit1.Lines.Add(Format('Home : %3.0d Away: %3.0d', [RoundRobinAry[i][ii][Home],RoundRobinAry[i][ii][Away]])) else Richedit1.Lines.Add(Format('BYE FOR TEAM : %3.0d', [RoundRobinAry[i][ii][Home]])); inc(ii); end; inc(i); ii := 1; until (RoundRobinAry[i][ii][Home] = 0); Richedit1.Lines.endupdate; end;