3

我正在制定联赛时间表,但我一直坚持在任何给定的一周内,一支球队应该只参加一次比赛。

到目前为止,我已经确定了正确的比赛场数,并且每支球队都与他们的同盟对手交手 4 次,与他们的跨区对手交手 2 次。这是我为此编写的代码:

let easternConfTeams = [a, b, c, d, e, f];
let westernConfTeams = [g, h, i, j, k, l];

const teamPool = [...easternConfTeams, ...westernConfTeams];

let schedule = teamPool.reduce((a, v, i) => {
  for (let j = i + 1; j < teamPool.length; j++) {
    if (i < 6) {
      if (j < 6) {
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
      } else {
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
      }
    } else {
      if (j < 6) {
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
      } else {
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
        a.push(`${v} : ${teamPool[j]}`);
      }
    }
  }
  return a;
}, []);

然后我通过一个 shuffle 函数运行它:

shuffle = (schedule) => {
  let currentIndex = schedule.length,
    temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = schedule[currentIndex];
    schedule[currentIndex] = schedule[randomIndex];
    schedule[randomIndex] = temporaryValue;
  }

  return schedule;
};

然而,我被困在最后一块,即将这个游戏时间表变成单独的几周。由于有 12 支球队,本赛季每周应该有 6 场比赛——在这 6 场比赛中,没有球队应该出现两次。换句话说,每支球队都应该每周打一场,但只能打一次。

总共有192场比赛,需要分成32周,每场6场。

我怎么能确保这一点?

4

1 回答 1

4

这是一种基于循环锦标赛调度算法的替代方法。

循环算法将生成一组轮次比赛,其中每支球队在每轮比赛中与其他球队匹配一次,而不会在任何一轮中重复比赛。然后,有一个步骤可以根据需要重复这些回合并交替比赛(模拟主场/客场交替)。所有团队之间的比赛轮次生成并重复两次。然后生成、合并和重复两次会议内比赛的回合(因为会议内球队已经有上一步的 2 场比赛)。

结果是 32 轮(周),每场 6 场比赛,每支球队在所有回合完成后与非会议对手比赛两次,在会议对手比赛 4 次。

const zip = (a, b) => a.map((e, i) => [e, b[i]]);
const combine = (a, b) => zip(a, b).map((e) => [...e[0], ...e[1]]);
const alternate = (rounds, repeats) => {
  const alt = [];
  for (let i = 0; i < repeats; i++) {
    const next = i % 2 ? rounds.map((r) => r.map((m) => [m[1], m[0]])) : rounds;
    alt.push(...next);
  }
  
  return alt;
};

const roundrobin = (teams) => {
  const rounds = [];
  const mid = teams.length / 2;
  for (let i = 0; i < teams.length - 1; i++) {
    const t = i ? [teams[0], ...teams.slice(-i), ...teams.slice(1, -i)] : teams;
    const t1 = t.slice(0, mid);
    const t2 = t.slice(mid).reverse();
    rounds.push(zip(t1, t2));
  }
  
  return rounds;
};

const east = ['a','b','c','d','e','f'];
const west = ['g','h','i','j','k','l'];
const schedule = [
  ...alternate(roundrobin([...east, ...west]), 2),
  ...alternate(combine(roundrobin(east), roundrobin(west)), 2)
];

console.log(schedule);

于 2019-09-17T19:17:05.520 回答