1
var players = [
{ id: 1, name : 'player1'},
{ id: 2, name : 'player2'},
{ id: 3, name : 'player3'},
{ id: 4, name : 'player4'},
{ id: 5, name : 'player5'},
{ id: 6, name : 'player6'},
{ id: 7, name : 'player7'},
{ id: 8, name : 'player8'},
{ id: 9, name : 'player9'},
{ id: 10, name : 'player10'},
{ id: 11, name : 'player11'},
{ id: 12, name : 'player12'},
{ id: 13, name : 'player13'},
{ id: 14, name : 'player14'},
{ id: 15, name : 'player15'},
{ id: 16, name : 'player16'}]

I want to toss games with 2 players aginst 2 players. So one round is 4 games with 2 vs 2.

One player can never be in team with a player it already played with.

I want to build a function that randomize all the games.

so i want something like this but with all the games in the turnament.

Then they play 4 games at the time and then switch players and 4 new games start.

games = [{ team1: [{ id: 1, name : 'player1'},{ id: 2, name : 'player2'}], team2 :[{ id: 3, name : 'player3'},{ id: 4, name : 'player4'}] }]
user1199595
  • 406
  • 2
  • 7
  • 16
  • 1
    Can you show us what you've tried so far? – Scott Sauyet Jun 11 '20 at 14:00
  • "One player can never be in team with a player it already played with." => Does that just mean, that same teams should never occur, or should it also be impossible, that members of an earlier team compete with each other? – Paul Jun 11 '20 at 19:56
  • Yes you can't have the same team-mate again. And I want as many rounds possible – user1199595 Jun 12 '20 at 04:33

1 Answers1

1

To get all combinations for a maximal number of possible games rounds (every player plays with each other player exactly once), I used https://math.stackexchange.com/a/3094469 as inspiration.

// From: https://stackoverflow.com/a/12646864/9487478
const shuffleArray = (array) => {
  let shuffledArray = [...array];
  for (let i = shuffledArray.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
  }
  return shuffledArray;
}

// Note: The number of players needs to be even.
let createGames = (playerArr) => {
  let players = [...playerArr];
  const teamsPerRound = [], 
        rounds = mod = players.length - 1,
        gamesPerRound = 4,
        // Helper for checking how often a player is confronted with another player.
        confrontations = Array(players.length).fill().map(x => Array(players.length).fill(0));        
    
  // Inspired by: https://math.stackexchange.com/a/3094469
  // Create as many unique teams as possible, whereas within a round every player occurs exactly once.
  for (let i = 0; i < rounds; i++) {
    let team = [[
      players.length - 1, 
      (players.length + i) % mod
    ]];
    for (let k = 1; k < (players.length / 2); k++) {
      team.push([
        (players.length + i + k) % mod,
        (players.length + i - k) % mod
      ]);
    }
    teamsPerRound.push(team);
    console.log(`Teams-Round ${i+1}`, JSON.stringify(team));
  }

  
  // Now that we have teams, we can create the games. Let's shuffle the teams per round before to ensure it's more random.
  const games = shuffleArray(teamsPerRound).map(teams => {
    let roundMatches = [];
    teams = shuffleArray(teams);
    for (let i = 0; i < teams.length/2; i++) {
      let first = teams[i], second = teams[teams.length - 1 - i];

      roundMatches.push({
        team1: first.map(x => ({...players[x]})),
        team2: second.map(x => ({...players[x]}))
      })
      
      // Helper for checking how often a player is confronted with another player.
      first.forEach(x => second.forEach(y => (confrontations[x][y]++, confrontations[y][x]++)));
    }
    return roundMatches;
  });
    
  confrontations.forEach((x,i) => console.log(`Confrontations (playerIndex: ${i})`, JSON.stringify(x), x.reduce((acc, val) => acc += val)));

  return games;
}

var players = [
  { id: 1, name : 'player1'},
  { id: 2, name : 'player2'},
  { id: 3, name : 'player3'},
  { id: 4, name : 'player4'},
  { id: 5, name : 'player5'},
  { id: 6, name : 'player6'},
  { id: 7, name : 'player7'},
  { id: 8, name : 'player8'},
  { id: 9, name : 'player9'},
  { id: 10, name : 'player10'},
  { id: 11, name : 'player11'},
  { id: 12, name : 'player12'},
  { id: 13, name : 'player13'},
  { id: 14, name : 'player14'},
  { id: 15, name : 'player15'},
  { id: 16, name : 'player16'}
];

const games = createGames(players);

console.log("Matches", games);
Paul
  • 2,086
  • 1
  • 8
  • 16
  • Thanks a lot, this give me 4 round. But I struggle to get more rounds. I want as many rounds as possible. – user1199595 Jun 12 '20 at 04:30
  • @user1199595 Hey, I did a rework. Please check my new solution. I think it should do the job. :) – Paul Jun 12 '20 at 12:27