dongpan1871 2018-08-18 11:49
浏览 66
已采纳

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

I am trying to expand and improve the round-robin algorithm from 1v1 group to a 1v1v1v1 group(something like free for all). I've made the function itself to do the schedule, but when I tried to expand it, some teams repetead. For example, I have 16 teams and I want to have 5 rounds, team 1 appears 7 times in 5 rounds and team2 appears 3 times in 5 rounds. I need them to appear 5 times at most.I really can't understand how I can do it. Any advice is welcomed and links.

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;
}

Rotate function:

   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;
}

For example:

If I set rounds to 5, every team play 5 matches. Array example Screenshot

Dealing with the 5th round:

Well, after I thought for a bit, maybe there isn't a way for them to play without repeatence, but if it is lowered to minumum, like every team should play 5 times only - this means once a round. That's what I meant. And what I meant under 'they repeat' is that there are like: 16 teams, 5 rounds and some teams are going like 7 times for all these rounds and other teams are going 3 times for these 5 rounds. I want to avoid this and to make every team play 5 rounds at most.

  • 写回答

1条回答 默认 最新

  • 普通网友 2018-08-18 13:07
    关注

    Your foreach() with the selection of the other 3 teams is wrong. One of them have to make steps with a multiple of 4. If you don't, you will select the teams at the beginning more than one and don't select the teams at the end of the array at all. This will result in wrong team matchups like this (teams are letters here):

    abcd
    bcde
    cdef
    defg
    

    And then your break; hits.

    Instead it should look something like this:

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

    This way you get the following pairing (again, using letters as teams):

    abcd
    efgh
    ijkl
    mnop
    

    This algorithm will split the team list in four groups:

    abcd|efgh|ijkl|mnop
    

    Keep in mind that depending on the shuffling of the $teams array for the next round you might get the same opponent twice.

    adei|klnf|gjmc|pobh
    

    Here the teams ad, kl and op will face again.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 基于单片机数字电压表电路组成及框图
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line