Forming a tournament table with LINQ (Fixture List)

前端 未结 3 1882
盖世英雄少女心
盖世英雄少女心 2020-12-30 18:39

I have an array of players (string[]) and now I need to get an array of pairs representing games (playerN-playerM) to orginize tournament table like at this picture:

相关标签:
3条回答
  • 2020-12-30 18:49

    The following code can be used to generate a fixture list for a collection of teams to ensure that each time plays all other teams in 1 home and 1 away match.

    The code is a bit long winded but it does work by providing you with a list in the order you have specified.

    The code can probably be optimised but at the moment this is how it has come from my head.

    NOTE: The resulting list will contain both Home and Away fixture, which based on your grid will be what you need to do anyway.

        class Fixture
        {
            public string Home { get; set; }
            public string Away { get; set; }
        }
    
        void CallCode()
        {
            string players = new string[] { "A", "B", "C", "D" };
            List<Fixture> fixtures = CalculateFixtures(players);
        }
    
        List<Fixture> CalculateFixtures(string[] players)
        {
            //create a list of all possible fixtures (order not important)
            List<Fixture> fixtures = new List<Fixture>();
            for (int i = 0; i < players.Length; i++)
            {
                for (int j = 0; j < players.Length; j++)
                {
                    if (players[i] != players[j])
                    {
                        fixtures.Add(new Fixture() { Home = players[i], Away = players[j] });
                    }
                }
            }
    
            fixtures.Reverse();//reverse the fixture list as we are going to remove element from this and will therefore have to start at the end
    
            //calculate the number of game weeks and the number of games per week
            int gameweeks = (players.Length - 1) * 2;
            int gamesPerWeek = gameweeks / 2;
    
            List<Fixture> sortedFixtures = new List<Fixture>();
    
            //foreach game week get all available fixture for that week and add to sorted list
            for (int i = 0; i < gameweeks; i++)
            {
                sortedFixtures.AddRange(TakeUnique(fixtures, gamesPerWeek));
            }
    
            return sortedFixtures;
        }
    
        List<Fixture> TakeUnique(List<Fixture> fixtures, int gamesPerWeek)
        {
            List<Fixture> result = new List<Fixture>();
    
            //pull enough fixture to cater for the number of game to play
            for (int i = 0; i < gamesPerWeek; i++)
            {
                //loop all fixture to find an unused set of teams
                for (int j = fixtures.Count - 1; j >= 0; j--)
                {
                    //check to see if any teams in current fixtue have already been used this game week and ignore if they have
                    if (!result.Any(r => r.Home == fixtures[j].Home || r.Away == fixtures[j].Home || r.Home == fixtures[j].Away || r.Away == fixtures[j].Away))
                    {
                        //teams not yet used
                        result.Add(fixtures[j]);
                        fixtures.RemoveAt(j);
                    }
                }
            }
    
            return result;
        }
    
    0 讨论(0)
  • 2020-12-30 18:54

    The implementation I really wanted:

    public static List<List<Tuple<string, string>>> ListMatches(List<string> listTeam)
    {
        var result = new List<List<Tuple<string, string>>>();
    
        int numDays = (listTeam.Count - 1);
        int halfSize = listTeam.Count / 2;
        var 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++)
        {
            var round = new List<Tuple<string, string>>();
            int teamIdx = day % teamsSize;
            round.Add(new Tuple<string, string>(teams[teamIdx], listTeam[0]));
    
            for (int idx = 1; idx < halfSize; idx++)
            {
                int firstTeam = (day + idx) % teamsSize;
                int secondTeam = (day + teamsSize - idx) % teamsSize;
    
                round.Add(new Tuple<string, string>(teams[firstTeam], teams[secondTeam]));
            }
            result.Add(round);
        }
        return result;
    }
    
    0 讨论(0)
  • 2020-12-30 19:06
    var games = players.SelectMany((player1, index) => 
        players.Skip(index + 1).
        Select(player2 => new {Player1 = player1, Player2 = player2}));
    

    That should do it...

    0 讨论(0)
提交回复
热议问题