Generating Fixture Lists

Update 2007-03-21: If all you want to do is generate a fixtures list you can use my Fixtures Generator

I’ve been trying to find out how to generate fixture lists for some time (it is harder than it sounds!) and I finally worked it out thanks to this page about a fixture generating algorithm. My Java implementation of the algorithm is below.

/* 
 * This code owes an enormous debt to 
 * http://www.barrychessclub.org.uk/berger2001.htm 
 */

import java.util.Arrays;

public class Fixtures2 {

    public static void main(String[] args) {
        
        // Find out how many teams we want fixtures for.
        int teams = 0;
        try {
            teams = Integer.parseInt(args[0]);
        } catch (NumberFormatException e) {
            System.err.println("Please state number of teams as first arg.");
            System.exit(0);
        }
        
        // If odd number of teams add a "ghost".
        boolean ghost = false;
        if (teams % 2 == 1) {
            teams++;
            ghost = true;
        }
        
        // Generate the fixtures using the cyclic algorithm.
        int totalRounds = teams - 1;
        int matchesPerRound = teams / 2;
        String[][] rounds = new String[totalRounds][matchesPerRound];
        
        for (int round = 0; round < totalRounds; round++) {
            for (int match = 0; match < matchesPerRound; match++) {
                int home = (round + match) % (teams - 1);
                int away = (teams - 1 - match + round) % (teams - 1);
                // Last team stays in the same place while the others
                // rotate around it.
                if (match == 0) {
                    away = teams - 1;
                }
                // Add one so teams are number 1 to teams not 0 to teams - 1
                // upon display.
                rounds[round][match] = (home + 1) + " v " + (away + 1);
            }
        }
        
        // Interleave so that home and away games are fairly evenly dispersed.
        String[][] interleaved = new String[totalRounds][matchesPerRound];
        
        int evn = 0;
        int odd = (teams / 2);
        for (int i = 0; i < rounds.length; i++) {
            if (i % 2 == 0) {
                interleaved[i] = rounds[evn++];
            } else {
                interleaved[i] = rounds[odd++];
            }
        }
        
        rounds = interleaved;

        // Last team can't be away for every game so flip them
        // to home on odd rounds.
        for (int round = 0; round < rounds.length; round++) {
            if (round % 2 == 1) {
                rounds[round][0] = flip(rounds[round][0]);
            }
        }
        
        // Display the fixtures        
        for (int i = 0; i < rounds.length; i++) {
            System.out.println("Round " + (i + 1));
            System.out.println(Arrays.asList(rounds[i]));
            System.out.println();
        }
        
        System.out.println();
        
        if (ghost) {
            System.out.println("Matches against team " + teams + " are byes.");
        }
        
        System.out.println("Use mirror image of these rounds for "
            + "return fixtures.");
    }

    private static String flip(String match) {
        String[] components = match.split(" v ");
        return components[1] + " v " + components[0];
    }
}

Update 2005-06-05: Now allows “complementary teams”, that is – teams that never play at home at the same time as each other. For example, try 10 teams — for each pair from 1 & 6, 2 & 7, 3 & 8, 4 & 9, and 5 & 10, both are never both at home. It was meant to be in the original program but a bug in my code was fouling things up.

Update 2007-03-21: You might also want to see the source code to my PHP fixtures generator

61 Replies to “Generating Fixture Lists”

  1. You have interleaved declared as a 2 dimensional array but it is not clear whether the line “interleaved[i] = rounds” is the zero or first indice in this array. Also, should “rounds.length” be the first indice also? Many thanks.

    // Interleave so that home and away games are fairly evenly dispersed.
    String[][] interleaved = new String[totalRounds][matchesPerRound];

    int evn = 0;
    int odd = (teams / 2);
    for (int i = 0; i < rounds.length; i++) { if (i % 2 == 0) { interleaved[i] = rounds[evn++]; } else { interleaved[i] = rounds[odd++]; } }

  2. At this stage we already have a complete set of rounds for the tournament. But they are not in an ideal order because some teams would play at home or away several times in a row. To get around this we mix up the rounds. It so happens that taking one from the first half then one from the second then one from the first and so on ends up with a much better arrangement so that’s how we do it.

    So, rounds is an array of arrays just like interleaved (it’s probably easier to think of it that way rather than as a multidimensional array although they are much the same thing). Which means we assign an array from rounds to the zeroth index of interleaved at each step until interleaved has one copy of each array in the array of arrays that is rounds.

    You could stop before this step but then some teams would have several home or away matches in a row.

    Does that make sense?

    I’m afraid I don’t understand the second question. rounds.length is the total size of the zeroth index of rounds.

  3. Is there a way to generate it with team names instead of having to change the team numbers to team names afterwards?

    For instance, English Prem League football team names.

  4. Hi Ragz,

    Not at the moment. You can use Find and Replace in your text editor or word processor to replace all 1s with Arsenal and all 2s with Aston Villa, etc. which should be nearly as easy as entering the team names first. Hope that helps.

  5. Yep, that’s pretty much how i did it.
    Thanks for responding though. Appreciated mate.
    If i can get the php written right, then i’ll send you some more source code if you like, as i’m working on an entire league system to generate a league table that will keep things updated with goals for, against, w/d/l, points, etc. All using php and mysql.

    Only part i’ve been having issues with is fixture generation, but the source you have here is helpful and if it’s ok with you, i’d like to try and work it into my whole thing and hopefully get it to use team names from the database.
    As if it uses those numbers it generates and references say a ‘TEAMID’ field in a database table, it could then echo the team names instead of numbers for each fixture.

    But i wanted to ask if it’s ok to use it before i did so.

  6. Just in case anyone else wants to know, it’s linked to from this page:

    http://bluebones.net/2005/05/league-fixtures-generator/

  7. Tom,

    i’ve been working on the php source to try and get it to do a str_replace() on the numbers and change them to teams. However, my knowledge of php isn’t as good as it could be and i’ve been trying to figure out where exactly i’d need to place the str_replace() to get it to function (if it will even work).
    Any thoughts on this one?

    Or the other option i was thinking of using would be to output the fixtures to a file and then have a second php function called to open that file and run a str_replace() on that file which would then either rewrite the file or preferable write the new results to a table in mysql.
    Again though, i’m hitting the proverbial brick wall. I can’t figure out exactly what i’d need to write into the file with fwrite() 😉

    Hopefully i’ve not overstayed my welcome by asking such questions, and if you don’t have time to assist, it’s all good, as i’m sure you’re probably busy.

    Thanks

  8. Well, so far so good.
    It’s now generating names via an array.
    Only it’s causing a little problem on every other round. Round 2 is missing the first two teams.
    Here’s what i’ve got so far:

    http://footy.darknessrising.net/fixtures_test.php

    and the source:
    http://footy.darknessrising.net/fixtures_test.txt

  9. This is what the output shows for 4 teams…

    Round 1
    Arsenal v Bolton Wanderers
    Aston Villa v Blackburn Rovers

    Round 2
    v
    Arsenal v Aston Villa

    Round 3
    Aston Villa v Bolton Wanderers
    Blackburn Rovers v Arsenal

    See in round 2 it’s got the invisible teams? hehe.
    If you can spot what’s up, i’d be most appreciative.
    As i’m stumped. It’s something to do with the array, but i can’t seem to stop it.

  10. Fixed.

    Got the teams working now. 😉
    http://footy.darknessrising.net/fixtures_test.php

    and the source:
    http://footy.darknessrising.net/fixtures_test.txt

  11. Tom, just to let you know, i figured it all out. Got it to write to a mysql db aswell.

    Once i’ve got my league sorted out, i’ll add in some extra code to the php fixtures generator to allow a user to input their team names aswell, in a second step of the input process.
    So it will then record those names into an array and output the entire set of rounds using team names instead of numbers.
    Once i’ve done it, i’ll put the source up for you so you can grab a copy of it and host it here.

  12. I’ve updated the fixtures generator to optionally allow you to enter team names instead of the number of teams.

  13. Hey Thomas, i’m doing my dissertion on a squash league fixture generator, and i was looking how you made your code. When i copy your code into JCreator and save it as the class name ‘Fixtures2’, it doesn’t work, it just comes up with the following, and i’m not sure why, any chance you could tell me why. Thanks Tim

    javac: invalid flag: D:\\Tim\\Squash League\\Website\\Fixtures2
    Usage: javac  
    where possible options include:
      -g                        Generate all debugging info
      -g:none                   Generate no debugging info
      -g:{lines,vars,source}    Generate only some debugging info
      -nowarn                   Generate no warnings
      -verbose                  Output messages about what the compiler is doing
      -deprecation              Output source locations where deprecated APIs are used
      -classpath          Specify where to find user class files
      -sourcepath         Specify where to find input source files
      -bootclasspath      Override location of bootstrap class files
      -extdirs            Override location of installed extensions
      -d             Specify where to place generated class files
      -encoding       Specify character encoding used by source files
      -source          Provide source compatibility with specified release
      -target          Generate class files for specific VM version
      -help                     Print a synopsis of standard options
    
  14. Hi Tim,

    I think you’re having a problem with configuration rather than with the code. If I copy this code into a text file and call it Fixtures2.java I can issue the following at a command prompt:

    $ javac Fixtures2.java
    $ java Fixtures2 4
    

    The first command compiles it and the second gives me a fixture list for four teams.

    I would try getting that working before you worry about using it in an IDE or as part of a package, etc.

    Hope that helps. Let me know if not.

  15. I must say I’m flattered. This whole thing works like majic. I was given a task to come up with a system to generate fixtures given the participating teams. I spent an entire night pondering over ths issue and ideas were all over and gat me pretty confused. I then decided to check if someone has done this and published for all to see and probably use. Just one search criteria gave me this solution. I must say that the net is as good as a life saver. I think I have all I need to get on with my life. Thanks to you!

  16. hiya,

    could you please help me ,i am the new fixture sec for our snooker league and this year we have five clubs each with 2 team total 10 teams who need to play each other 3 times,i have tried to put a fixture list together but i find it impossible. the teams have to play each other home and away but if team 1 is at home then team 2 must be away.
    Could you please e-mail me if you can help or need any further inf
    Thanks Martin

  17. I love this application but I am a non-programmer and I was wondering if there is a simple way to adapt the code to allow each team to play each other only once rather than Home and Away?

  18. Mike, you can get a play-only-once fixture list by just using the first half of the season generated by my fixtures generator. Hope that helps!

  19. I have 14 teams in my Domino league, 4 teams 2A & 2B from 2 different clubs.
    Have you a fixture matrix for 14 teams which will ensure that Teams 1 A & B
    and Teams 2 A & B will always be opposite to each other. At the same time ensuring that all the other 10 teams only have a maximum of 2 or 3 consecutive Home or Away fixtures.

  20. I know a little basic programmming in VB3/VB5. Has anybody converted it to basic as I don’t have the skills to convert Java.

    Cheers

  21. @Geoff – You might get more joy posting your question here – http://bluebones.net/2005/05/league-fixtures-generator/ – where the FIXTUREMAN lurks …

    @Peter – There is no basic version but there is a version in PHP – http://bluebones.net/fixtures.txt – any good?

  22. Hi

    i was looking at your fixture generator, are you able to provide a solution to a two problems.

    Run the fixture however i need the teams that have a home game in round 1 , must finish away in final round ( 14 team league)

    Also no team can have more than two consective games away or home in a row.

    can you provide a solution in the fixture generator to do this please ?

  23. @james – The list generated by the fixtures generator at http://bluebones.net/fixtures.php?teams=14 satisfies your first criteria. I don’t think it is possible to satisfy the second.

  24. Guys,

    Really good stuff – am running this in Excel so VBA and have converted the code

    Anyone pls explain the INTERLEAVE Section ??

    Seems to say
    1.Set variables evn and odd
    2. Loop through all rounds, and test if its odd/even, switching all matches in the even rounds.

    Can anyone explain what “interleaved[i] = rounds[evn++];” does ? I know it sets part of interleaved array to part of rounds, but which ones

    I would guess that we are grabbing (in order) for say an array of 16 teams
    Rounds 1,9,2,10,3,11,4,12,5,13,6,14,7,15,8

    Anyone care to comment, or suggest an alternative

    S
    eg, All Matches in ROUND 2 get switched with

  25. @Steve – The purpose of the interleaving is as you suggest to take the first half of the set of fixtures we have generated and interleave them with the second half because it gives a more pleasing arrangement of who is home or away in what order.

    So if we generated sets of fixtures A B C D E F G H the “interleaved” version would be A E B F C G D H.

    It may help to look at the PHP source code at bluebones.net/fixtures.txt. Or it may not 🙂

  26. Thanks bakert for a quick answer.

    Now works great, and even handles ‘complementary’ teams as it said. Code is much cleaner in php – should really sit down and learn it some time :0

    The original code i had used was decompiled from an Old DOS batch file, and worked pretty much ok. I had lived with its problems until recently, but this is much clearer, and does everything thats needed

    Thanks again..
    S

  27. One more poser ?…

    Interleaving is fine, but if you have an odd number of teams, requiring a ‘ghost’ team – this approach gives an imbalance between home and away matches.

    eg; With 7 teams, each team plays 6 games and there should be 3 home and 3 away. Unless I have the logic wrong, this approach gives some teams having 2 home / 4 away and vice versa??

    S

  28. @Steve – The first seven rounds in a seven team competition generated by my generator are:

    Round 1
    
    2 v 7
    3 v 6
    4 v 5
    
    Round 2
    
    6 v 4
    7 v 3
    1 v 2
    
    Round 3
    
    3 v 1
    4 v 7
    5 v 6
    
    Round 4
    
    7 v 5
    1 v 4
    2 v 3
    
    Round 5
    
    4 v 2
    5 v 1
    6 v 7
    
    Round 6
    
    1 v 6
    2 v 5
    3 v 4
    
    Round 7
    
    5 v 3
    6 v 2
    7 v 1
    

    In this scenario everyone misses one match (versus phantom team number 8) and plays three home matches.

    The second half of the season (if everyone plays everyone else both home and away) is a mirror and has the same 3 home matches each.

    I’m not sure if this holds for every possible combination but I believe it does.

  29. Hey i am not that good with this whole programming thing, but i can’t seem to find out how to add the number of teams in the code?

  30. @Ducklas – in the java code above it is expected to be passed as the first argument to the program.

    You could replace:

            // Find out how many teams we want fixtures for.
            int teams = 0;
            try {
                teams = Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                System.err.println("Please state number of teams as first arg.");
                System.exit(0);
            }
    

    with:

          int teams = 10; // or whatever number of teams you want
    

    but then the program will always produce the same set of fixtures. If you want that you might as well use my fixtures generator – bluebones.net/fixtures.php – and hardcode the results in your program.

    Hope that helps!

  31. The mirror thing is just that to get the complete set of home and away fixtures you should reverse the order of the fixtures produced and swap who is at home and away. In a simple example:

    1 v 4
    2 v 3

    4 v 3
    1 v 2

    2 v 4
    3 v 1

    would add on to the end:

    4 v 2
    1 v 3

    3 v 4
    2 v 1

    4 v 1
    3 v 2

  32. Hi Ragz,

    I know this is a long shot, but if you still visit this page could you please post some information you said you would involving database’s etc… I am working on a very similar project and I am having some trouble.. Would greatly appreciate any help please.

  33. I know virtually no coding but also know a little vba in excel. I would like a version I can integrate into my rather massive spreadsheet.

    If anyone has a version or alternatively give me a brief explanation of the main for loops I may be able to re engineer. Any help would be much appreciated.

    peter@eaba.co.uk

  34. @pocketpete – The principle at work here is that one team stays “in place” and the other teams rotate around them. In this example team 4 stays in place and the others rotate around them:

    1 v 4
    2 v 3

    2 v 4
    3 v 1

    3 v 4
    1 v 2

    It’s kind of hard to see what’s going on there with so few teams so here’s the first two rounds of a ten team example:

    1 v 10
    2 v 9
    3 v 8
    4 v 7
    5 v 6

    2 v 10
    3 v 1
    4 v 9
    5 v 8
    6 v 7

    That produces a round robin and might be as far as you need to go.

    If your competition has a concept of home and away you will need flip half of the matches involving the team that stays in the fixed position.

    Additionally you get a better distribution of home and away (no “3 games on the road”) if you interleave the odd-numbered rounds with the even-numbered rounds instead of leaving them in the generated order.

    If you need both home and away matches between each pair of teams in your competition you can mirror the first half of the season for the second half of the season.

  35. Hi,
    Does the fixture generated at http://bluebones.net/fixtures.php?teams=8 handle ‘complementary’ teams and if so what are the ‘complementary’ team groupings.

    Thanks,

    Peter

  36. Hi Peter, yes it does. The complimentary teams are 1 & 5, 2 & 6, 3 & 7, 4 & 8. In general the fixtures generator produces pairs of complimentary teams that are team number + half of total number of teams for each team.

  37. Hi, thanks for sharing.

    Is there a simple way to make this logic random?
    If for example we have several seasons, it’s preferred that in each season the fixture will be different.

    I’m thinking the easiest way to have it random is at each call, randomly reorder the list of teams. But wondering if there are are technique.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.