话不多说,直接上代码:
<?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();