将循环锦标赛1v1扩展到1v1v1v1

时间:2018-08-18 11:49:46

标签: php round-robin

我正在尝试将循环算法从1v1组扩展到1v1v1v1组(所有人都免费)。我已经使函数本身完成了日程安排,但是当我尝试扩展日程安排时,一些团队却不断重复。例如,我有16支球队,我希望有5轮回合,第1队在5回合中出现7次,而team2在5回合中出现3次。我最多需要让它们出现5次。我真的不明白该怎么做。欢迎任何建议和链接。

function make_schedule(array $teams, int $rounds = null, bool $shuffle = true, int $seed = null): array
{


    $teamCount = count($teams);


   if($teamCount < 4) {
        return [];
    }
    //Account for odd number of teams by adding a bye
    if($teamCount % 2 === 1) {
        array_push($teams, null);
        $teamCount += 1;
    }
    if($shuffle) {
        //Seed shuffle with random_int for better randomness if seed is null
        srand($seed ?? random_int(PHP_INT_MIN, PHP_INT_MAX));
        shuffle($teams);
    } elseif(!is_null($seed)) {
        //Generate friendly notice that seed is set but shuffle is set to false
        trigger_error('Seed parameter has no effect when shuffle parameter is set to false');
    }
    $quadTeamCount = $teamCount / 4;
    if($rounds === null) {
        $rounds = $teamCount - 1;
    }

    $schedule = [];

    for($round = 1; $round <= $rounds; $round += 1) {
        $matchupPrev = null;

        foreach($teams as $key => $team) {
            if($key >= $quadTeamCount ) {
                break;
            }

            $keyCount = $key + $quadTeamCount;
            $keyCount2 = $key + $quadTeamCount + 1;
            $keyCount3 = $key + $quadTeamCount + 2;


            $team1 = $team;
            $team2 = $teams[$keyCount];
            $team3 = $teams[$keyCount2];
            $team4 = $teams[$keyCount3];


            //echo "<pre>Round #{$round}: {$team1} - {$team2} - {$team3} - {$team4} == KeyCount: {$keyCount} == KeyCount2: {$keyCount2} == KeyCount3: {$keyCount3}</pre>";

            //Home-away swapping
            $matchup = $round % 2 === 0 ? [$team1, $team2, $team3, $team4 ] : [$team2, $team1, $team4, $team3];

            $schedule[$round][] = $matchup ;
        }
        rotate($teams);
    }

    return $schedule;
}

旋转功能:

   function rotate(array &$items)
{
    $itemCount = count($items);
    if($itemCount < 3) {
        return;
    }
    $lastIndex = $itemCount - 1;
    /**
     * Though not technically part of the round-robin algorithm, odd-even 
     * factor differentiation included to have intuitive behavior for arrays 
     * with an odd number of elements
     */
    $factor = (int) ($itemCount % 2 === 0 ? $itemCount / 2 : ($itemCount / 2) + 1);
    $topRightIndex = $factor - 1;
    $topRightItem = $items[$topRightIndex];
    $bottomLeftIndex = $factor;
    $bottomLeftItem = $items[$bottomLeftIndex];
    for($i = $topRightIndex; $i > 0; $i -= 1) {
        $items[$i] = $items[$i - 1];
    }
    for($i = $bottomLeftIndex; $i < $lastIndex; $i += 1) {
        $items[$i] = $items[$i + 1];
    }
    $items[1] = $bottomLeftItem;
    $items[$lastIndex] = $topRightItem;
}

例如:

如果我将回合设置为5,则每个团队进行5场比赛。 Array example Screenshot

第五轮交易:

好吧,在我想了一下之后,也许没有办法让他们没有重复,但是如果降低到最低,就像每支球队只能参加5次一样-这意味着每回合一次。我正是这个意思。我在“重复”下的意思是:16支球队,5轮比赛,有些球队在所有这些回合中都进行7次,而其他球队在这5回合中进行3次。我想避免这种情况,并让每个团队最多玩5轮。

1 个答案:

答案 0 :(得分:1)

您选择其他3支球队的foreach()是错误的。其中之一必须使用4的倍数来执行步骤。如果您不这样做,则将在多个开始处选择团队,而根本不在阵列末尾选择团队。这将导致这样的团队对决错误(团队在这里是字母):

abcd
bcde
cdef
defg

然后您的break;命中。

相反,它应该看起来像这样:

for ($i=0; $i<4; $i++) {
    $matchup = array();
    for ($j=0; $j<4; $j++) {
        $matchup[] = $teams[4*$i+$j];
    }
    $schedule[$round][] = $matchup ;
}

通过这种方式,您可以获得以下配对(同样,以字母为团队):

abcd
efgh
ijkl
mnop

此算法会将团队列表分为四组:

abcd|efgh|ijkl|mnop

请记住,根据下一轮$teams数组的改组,您可能会两次遇到相同的对手。

adei|klnf|gjmc|pobh

adklop团队将再次面对。