单循环赛制是一种多队伍进行比赛,每只队伍均能和其他队伍进行一次比赛的赛制。百科链接
比如有6只队伍,需要进行5轮比赛。编排如下:
想象一下赛场上站着每只队伍的代表,站两排,然后移动位置
| 轮数 | 左侧 | 右侧 | 
| 第一轮 | 1 | 6 | 
| 2 | 5 | |
| 3 | 4 | |
| 第二轮 | 1 | 5 | 
| 6 | 4 | |
| 2 | 3 | |
| 第三轮 | 1 | 4 | 
| 5 | 3 | |
| 6 | 2 | |
| 第四轮 | 1 | 3 | 
| 4 | 2 | |
| 5 | 6 | |
| 第五轮 | 1 | 2 | 
| 3 | 6 | |
| 4 | 5 | 
可能不太直观的看出来过程,下边用图标示一下移动的队伍。

直观的看,也看不出来如何用程序实现。再把两排看成一排试试。。。
| 轮数 | 站成一排的效果(尾尾相接) | 
| 第一轮 | 1 2 3 4 5 6 | 
| 第二轮 | 1 6 2 3 4 5 | 
| 第三轮 | 1 5 6 2 3 4 | 
| 第四轮 | 1 4 5 6 2 3 | 
| 第五轮 | 1 3 4 5 6 2 | 
清晰明了了:从第二轮开始,每轮从队尾抽过来1个队站在第一队后边。
PHP代码验证:
$teams = range(1, 6);
$loop = count($teams) - 1;
$half = count($teams) / 2;
for ($i=1; $i <= $loop; $i++) { 
    echo "第 $i 轮:", PHP_EOL;
    if ($i == 1) {
        $tmpTeams = $teams;
    }else{
        $x = $i - 1;
        $tmpTeams = array_merge([$teams[0]], array_slice($teams, -$x), array_slice($teams, 1, -$x));
    }
    $left = array_slice($tmpTeams, 0, $half);
    $right = array_slice($tmpTeams, $half);
    $right = array_reverse($right);
    echo '   left: ', implode(',', array_map(function($v){return str_pad($v, 3, ' ', STR_PAD_LEFT);}, $left)), PHP_EOL;
    echo '  right: ', implode(',', array_map(function($v){return str_pad($v, 3, ' ', STR_PAD_LEFT);}, $right)), PHP_EOL;
    echo PHP_EOL;
}
结果如下:
第 1 轮:
   left:   1,  2,  3
  right:   6,  5,  4
第 2 轮:
   left:   1,  6,  2
  right:   5,  4,  3
第 3 轮:
   left:   1,  5,  6
  right:   4,  3,  2
第 4 轮:
   left:   1,  4,  5
  right:   3,  2,  6
第 5 轮:
    left:   1,  3,  4
   right:   2,  6,  5
然后,封装后可使用的函数,传递一个队伍数组进来,并且提供当前是第几轮,返回左右两边的队伍数组。
/**
 * 获取单循环赛制某轮的队伍编排
 * @param array $teams 队伍数组
 * @param int $round 第几轮
 * @return array|bool 左右两只队伍的数组
 */
function getSingleLoopCompetitionTeams($teams, $round){
    // 单循环赛制轮数等于总队伍数-1
    if ($round > count($teams) - 1) {
        return false;
    }
    $half = count($teams) / 2;
    if ($round > 1) {
        $x = $round - 1;
        $teams = array_merge([$teams[0]], array_slice($teams, -$x), array_slice($teams, 1, -$x));
    }
    $left = array_slice($teams, 0, $half);
    $right = array_slice($teams, $half);
    $right = array_reverse($right);
    return [$left, $right];
}
获取某只队伍在某轮的对手:
/**
 * 获取某队伍在某轮的对手队伍
 * @param array $teams
 * @param int $round
 * @param int|string $team 队伍标识
 * @return int|string|false|null
 */
function getTargetTeam($teams, $round, $team)
{
    $result = getSingleLoopCompetitionTeams($teams, $round);
    if ($result === false) {
        return false;
    }
    list($left, $right) = $result;
    foreach ($left as $k => $lTeam) {
        if ($team == $lTeam) {
            return $right[$k];
        }
    }
    foreach ($right as $k => $rTeam) {
        if ($team == $rTeam) {
            return $left[$k];
        }
    }
    return null;
}