蛇形编排 同队限制(即同队的不允许在同一组)demo

话不多说,直接上代码:

<?php
/**
 * 蛇形编排 同队限制(即同队的不允许在同一组)demo
 *
 * @param  $players 参赛选手列表
 * @param  $group_num 分组数
 * @return void
 */
function snake_group($players, $group_num)
{
    // 初始化分组数组
    // $groups = array_fill(0, $group_num, []);

    // 记录每个队伍的选手数量
    $team_counts = [];
    $total_player = count($players); //总参赛人数

    // 计算每个队伍的选手数量
    foreach ($players as $player) {
        $team = $player['team'];
        if (!isset($team_counts[$team])) {
            $team_counts[$team] = 0;
        }
        $team_counts[$team]++;
    }
    foreach ($team_counts as $kt => $vt) {
        // 如果某队人数大于分组数 则肯定会出现一组中某队出现多队员的情况 需进行拦截处理 xpy_无(代表不属于任何队伍)
        if ($kt!='xpy_无' && $vt > $group_num){
            throw new \Exception("参赛选手数据不满足当前所选的分组规则,请更换!");
        }
    }

    // // 蛇形编排填充
    $direction = 1; // 1 表示正向,-1 表示反向
    $currentGroupIndex = 0;
    $number = 1;

    $snakeGroup = [];
    // 分组逻辑
    foreach ($players as $player) {
        $team = $player['team'];
        // 计算当前队伍的选手应该分配到哪个组
        // $group_index = ($team_count - 1) % $group_num;
        $group_index = ($currentGroupIndex + $group_num) % $group_num;
        // 更新方向和当前分组索引
        $currentGroupIndex += $direction;
        // 判断是否需要改变方向
        if ($currentGroupIndex >= $group_num || $currentGroupIndex < 0) {
            $direction *= -1;
            $currentGroupIndex += $direction;
        }
        // 将选手分配到对应组
        // $groups[$group_index][] = $player;
        // $groups[$group_index][] = []; //先将每组的人数蛇形编排占位

        //先计算每个组的编号  然后依据编号进行分配选手
        $snakeGroup[] = [
            'group'             => $group_index + 1,
            'number'            => $number++,
            'direction'         => $direction,
            'currentGroupIndex' => $currentGroupIndex,
        ];
    }

    $lastGroup     = [];
    $lastDirection = null;
    $lastGroup2    = null;
    foreach ($snakeGroup as $group_key => $group_value) {
        $group_number  = $group_value['group']; //当前要分配给的组号 下标从0开始
        foreach ($players as $player_key=> $player_data) {
            if(isset($lastGroup[$group_number]) && $lastGroup[$group_number]){
                $teams = array_column($lastGroup[$group_number], 'team');
                // 没有代表队的个人 每个人按不同的队算
                if ($player_data['team']!='xpy_无' && in_array($player_data['team'], $teams)) {
                    continue;
                }
            }
            $lastGroup[$group_number][] = $player_data;
            unset($players[$player_key]);
            $lastDirection = $group_value['direction'];
            $lastGroup2    = $group_value['currentGroupIndex']+1;
            break;
        }
    }
    // echo '<pre>';
    // print_r($players);
    // die();
    if ($players) {
        while (true) {
            foreach ($players as $playerKey => $playerValue) {
                if ($lastDirection < 0) { // 反向蛇形编排
                    for ($i = $group_num; $i >= 1; $i--) {

                        if ($i > $lastGroup2) {
                            // echo "3";
                            // echo "<pre>";
                            // print_r('当前组' . $lastGroup2);
                            // echo "<pre>";
                            // print_r($playerValue);
                            continue;
                        }
                        if (!isset($lastGroup[$i])) {
                            $lastGroup[$i] = [];
                        }
                        $teams = array_column($lastGroup[$i], 'team');
                        if ($playerValue['team'] != 'xpy_无' && in_array($playerValue['team'], $teams)) {
                            // echo "4";
                            // echo "<pre>";
                            // print_r('当前组' . $lastGroup2);
                            // echo "<pre>";
                            // print_r($playerValue);
                            if ($i != 1) {
                                $lastGroup2--;
                            }
                            // echo "<pre>";
                            // print_r('当前组--' . $lastGroup2);
                            if ($i == 1) {
                                $lastDirection *= -1;
                                break 2;
                            }
                            continue;
                        }

                        $lastGroup[$i][] = $playerValue;
                        unset($players[$playerKey]);

                        break;
                    }
                } else { // 正向蛇形编排
                    for ($i = 1; $i <= $group_num; $i++) {

                        if ($i < $lastGroup2) {
                            // echo "1";
                            // echo "<pre>";
                            // print_r('当前组' . $lastGroup2);
                            // echo "<pre>";
                            // print_r($playerValue);
                            continue;
                        }
                        if (!isset($lastGroup[$i])) {
                            $lastGroup[$i] = [];
                        }

                        $teams = array_column($lastGroup[$i], 'team');
                        if ($playerValue['team'] != 'xpy_无' && in_array($playerValue['team'], $teams)) {
                            // echo '2';
                            // echo "<pre>";
                            // print_r('当前组' . $lastGroup2);
                            // echo "<pre>";
                            // print_r($playerValue);
                            if ($i != $group_num) {
                                $lastGroup2++;
                            }
                            // echo "<pre>";
                            // print_r('当前组++' . $lastGroup2);
                            if ($i == $group_num) {
                                $lastDirection *= -1;
                                break 2; //跳出foreach 重新foreach
                            }
                            continue;
                        }
                        $lastGroup[$i][] = $playerValue;
                        unset($players[$playerKey]);
                        break;
                    }
                }
            }
            if (empty($players)) {
                break;
            }
        }
    }

    // echo '<pre>';print_r($lastGroup);die();
    // error_log(var_export(['players'=>$players],true),3,__FILE__.'--00000--.log');
    // 最终检查
    // echo "<pre>";print_r($lastGroup);die();
    $group_player_total = 0;
    foreach ($lastGroup as $group) {
        $group_player_total += count($group);
        $teams = array_column($group, 'team');
        //去除没有代表队的个人 每个人按不同的队算
        $teams = array_filter($teams, function ($team) {
            return $team != 'xpy_无';
        });
        $unique_teams = array_unique($teams);
        if (count($teams) !== count($unique_teams)) {
            $diffTeamsArr = array_diff_assoc($teams,$unique_teams);
            $diff = implode(',',$diffTeamsArr);
            throw new \Exception("Error: One group contains multiple players from the same team.".$diff);
        }
    }
    if($group_player_total!=$total_player){
        throw new \Exception("分组失败,请选择其他规则分组!");
    }

    return $lastGroup;
}

function someFunction()
{
    $group_num = 6;
    $players = [
        ['id' => 1, 'team' => 'A'],
        ['id' => 2, 'team' => 'xpy_无'],
        ['id' => 3, 'team' => 'A'],
        ['id' => 4, 'team' => 'A'],
        ['id' => 5, 'team' => 'A'],
        ['id' => 6, 'team' => 'A'],
        ['id' => 7, 'team' => 'B'],
        ['id' => 8, 'team' => 'B'],
        ['id' => 9, 'team' => 'B'],
        ['id' => 10, 'team' => 'B'],
        ['id' => 11, 'team' => 'xpy_无'],
        ['id' => 12, 'team' => 'B'],
        ['id' => 13, 'team' => 'xpy_无'],
        ['id' => 14, 'team' => 'C'],
        ['id' => 15, 'team' => 'C'],
        ['id' => 16, 'team' => 'C'],
        ['id' => 17, 'team' => 'C'],
        ['id' => 18, 'team' => 'C'],
        ['id' => 19, 'team' => 'D'],
        ['id' => 20, 'team' => 'D'],
        ['id' => 21, 'team' => 'D'],
        ['id' => 22, 'team' => 'D'],
        ['id' => 23, 'team' => 'xpy_无'],
        ['id' => 24, 'team' => 'D'],
        ['id' => 25, 'team' => 'E'],
        ['id' => 26, 'team' => 'xpy_无'],
        ['id' => 27, 'team' => 'E'],
        ['id' => 28, 'team' => 'E'],
        ['id' => 29, 'team' => 'E'],
        ['id' => 30, 'team' => 'E'],
        ['id' => 31, 'team' => 'D'],
        ['id' => 32, 'team' => 'C'],
        ['id' => 33, 'team' => 'B'],
        ['id' => 34, 'team' => 'A'],
        ['id' => 35, 'team' => 'E'],
    ];
    // $players = [
    //     ['id' => 1, 'team' => 'A'],
    //     ['id' => 2, 'team' => 'xpy_无'],
    //     ['id' => 3, 'team' => 'A'],
    //     ['id' => 4, 'team' => 'A'],
    //     ['id' => 5, 'team' => 'A'],
    //     ['id' => 6, 'team' => 'A'],

    //     ['id' => 7, 'team' => 'B'],
    //     ['id' => 8, 'team' => 'B'],
    //     ['id' => 9, 'team' => 'B'],
    //     ['id' => 10, 'team' => 'B'],
    //     ['id' => 11, 'team' => 'xpy_无'],
    //     ['id' => 12, 'team' => 'B'],

    //     ['id' => 13, 'team' => 'C'],
    //     ['id' => 14, 'team' => 'xpy_无'],
    //     ['id' => 15, 'team' => 'C'],
    //     ['id' => 16, 'team' => 'C'],
    //     ['id' => 17, 'team' => 'C'],
    //     ['id' => 18, 'team' => 'C'],

    //     ['id' => 19, 'team' => 'D'],
    //     ['id' => 20, 'team' => 'D'],
    //     ['id' => 21, 'team' => 'D'],
    //     ['id' => 22, 'team' => 'D'],
    //     ['id' => 23, 'team' => 'xpy_无'],
    //     ['id' => 24, 'team' => 'D'],

    //     ['id' => 25, 'team' => 'xpy_无'],
    //     ['id' => 26, 'team' => 'xpy_无'],
    //     ['id' => 27, 'team' => 'A'],
    //     ['id' => 28, 'team' => 'B'],
    //     ['id' => 29, 'team' => 'C'],
    //     ['id' => 30, 'team' => 'D'],

    // ];

    // $group_num = 5;
    // $players = [
    //     ['id' => 1, 'team' => 'A'],
    //     ['id' => 2, 'team' => 'xpy_无'],
    //     ['id' => 3, 'team' => 'A'],
    //     ['id' => 4, 'team' => 'A'],
    //     ['id' => 5, 'team' => 'A'],

    //     ['id' => 6, 'team' => 'B'],
    //     ['id' => 7, 'team' => 'B'],
    //     ['id' => 8, 'team' => 'B'],
    //     ['id' => 9, 'team' => 'xpy_无'],
    //     ['id' => 10, 'team' => 'B'],

    //     ['id' => 11, 'team' => 'C'],
    //     ['id' => 12, 'team' => 'xpy_无'],
    //     ['id' => 13, 'team' => 'C'],
    //     ['id' => 14, 'team' => 'C'],
    //     ['id' => 15, 'team' => 'C'],

    //     ['id' => 16, 'team' => 'A'],
    //     ['id' => 17, 'team' => 'B'],
    //     ['id' => 18, 'team' => 'C'],
    // ];

    // $group_num = 4;
    // $players = [
    //     ['id' => 1, 'team' => 'D'],
    //     ['id' => 2, 'team' => 'xpy_无'],
    //     ['id' => 3, 'team' => 'D'],
    //     ['id' => 4, 'team' => 'D'],
    //     ['id' => 5, 'team' => 'A'],
    //     ['id' => 6, 'team' => 'C'],
    //     ['id' => 7, 'team' => 'A'],
    //     ['id' => 8, 'team' => 'C'],
    //     ['id' => 9, 'team' => 'C'],
    //     ['id' => 10, 'team' => 'C'],
    //     ['id' => 11, 'team' => 'xpy_无'],
    //     ['id' => 12, 'team' => 'D'],
    // ];

    // $group_num = 3;
    // $players = [
    //     ['id' => 1, 'team' => 'A'],
    //     ['id' => 2, 'team' => 'B'],
    //     ['id' => 3, 'team' => 'B'],
    //     ['id' => 4, 'team' => 'A'],
    //     ['id' => 5, 'team' => 'A'],
    //     ['id' => 6, 'team' => 'xpy_无'],
    //     ['id' => 7, 'team' => 'xpy_无'],
    //     ['id' => 8, 'team' => 'xpy_无'],
    //     ['id' => 9, 'team' => 'B'],
    // ];

    // $group_num = 3;
    // $players = [
    //     ['id' => 1, 'team' => 'A'],
    //     ['id' => 2, 'team' => 'B'],
    //     ['id' => 3, 'team' => 'C'],
    //     ['id' => 4, 'team' => 'A'],
    //     ['id' => 5, 'team' => 'B'],
    //     ['id' => 6, 'team' => 'B'],
    //     ['id' => 7, 'team' => 'A'],
    //     ['id' => 8, 'team' => 'C'],
    //     ['id' => 9, 'team' => 'C'],
    // ];

    // $group_num = 3;
    // $players = [
    //     ['id' => 1, 'team' => 'D'],
    //     ['id' => 2, 'team' => 'A'],
    //     ['id' => 3, 'team' => 'B'],
    //     ['id' => 4, 'team' => 'C'],
    //     ['id' => 5, 'team' => 'C'],
    //     ['id' => 6, 'team' => 'A'],
    //     ['id' => 7, 'team' => 'B'],
    //     ['id' => 8, 'team' => 'B'],
    //     ['id' => 9, 'team' => 'D'],
    //     ['id' => 10, 'team' => 'D'],
    //     ['id' => 11, 'team' => 'C'],
    // ];

    // $group_num = 4;
    // $players = [
    //     ['id' => 1, 'team' => 'A'],
    //     ['id' => 2, 'team' => 'xpy_无'],
    //     ['id' => 3, 'team' => 'A'],
    //     ['id' => 4, 'team' => 'A'],
    //     ['id' => 5, 'team' => 'B'],
    //     ['id' => 6, 'team' => 'B'],
    //     ['id' => 7, 'team' => 'C'],
    //     ['id' => 8, 'team' => 'C'],
    //     ['id' => 9, 'team' => 'D'],
    //     ['id' => 10, 'team' => 'D'],
    //     ['id' => 11, 'team' => 'B'],
    //     ['id' => 12, 'team' => 'A'],
    // ];

    try {
        $team_groups = snake_group($players, $group_num);
        // 输出结果
        echo "<pre>";print_r($team_groups);die();
    } catch (\Exception $e) {
        echo "Error: " . $e->getMessage();die();
    }
}
someFunction();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值