PHP实现10名选手两轮配对:如何避免重复对阵问题
解决两轮选手抽签避免重复对阵的PHP方案
首先,咱们得明确核心问题:要确保两轮比赛里,任何一对选手不管顺序如何都不能重复对阵(比如首轮9-7和次轮7-9属于重复,必须避免)。下面是具体的实现思路和代码:
核心思路
- 第一轮正常随机配对,同时把所有配对以无序标识的方式存储(比如把配对的两个选手编号按从小到大排序后拼接成字符串,像
"7-9"),这样不管顺序如何都能准确判断是否重复。 - 第二轮生成配对时,每次都检查新生成的配对是否已经在第一轮的配对集合里,如果重复就重新打乱抽签,直到生成的所有配对都符合要求。
完整实现代码
<?php $totalPlayers = 10; // 第一轮抽签 $firstRoundPlayers = range(1, $totalPlayers); shuffle($firstRoundPlayers); $firstRoundPairs = []; $usedPairs = []; // 存储第一轮的配对标识,用于第二轮校验 // 生成第一轮配对并记录重复标识 for ($i = 0; $i < $totalPlayers; $i += 2) { $player1 = $firstRoundPlayers[$i]; $player2 = $firstRoundPlayers[$i + 1]; // 生成无序标识:小的编号在前,大的在后 $pairKey = min($player1, $player2) . '-' . max($player1, $player2); $firstRoundPairs[] = "$player1-$player2"; $usedPairs[] = $pairKey; } // 第二轮抽签:确保无重复配对 $secondRoundPairs = []; $valid = false; while (!$valid) { $secondRoundPlayers = range(1, $totalPlayers); shuffle($secondRoundPlayers); $currentPairs = []; $currentPairKeys = []; $hasDuplicate = false; // 生成当前尝试的第二轮配对 for ($i = 0; $i < $totalPlayers; $i += 2) { $p1 = $secondRoundPlayers[$i]; $p2 = $secondRoundPlayers[$i + 1]; $pairKey = min($p1, $p2) . '-' . max($p1, $p2); // 检查是否和第一轮重复 if (in_array($pairKey, $usedPairs)) { $hasDuplicate = true; break; // 有重复就终止当前尝试,重新打乱 } $currentPairs[] = "$p1-$p2"; $currentPairKeys[] = $pairKey; } // 如果当前尝试的配对没有重复,就确认有效 if (!$hasDuplicate) { $secondRoundPairs = $currentPairs; $valid = true; } } // 输出结果 echo "第一轮对阵:\n"; foreach ($firstRoundPairs as $pair) { echo "- $pair\n"; } echo "\n第二轮对阵:\n"; foreach ($secondRoundPairs as $pair) { echo "- $pair\n"; } ?>
代码说明
- 第一轮处理:用
shuffle()打乱选手顺序后两两配对,同时生成无序的pairKey存入usedPairs数组,这个数组就是咱们的"黑名单",第二轮绝对不能出现这些配对。 - 第二轮处理:用循环不断尝试打乱配对,只要发现任何一个配对在
usedPairs里,就直接放弃当前结果重新来,直到生成完全不重复的配对集合。 - 适配性:代码里的
$totalPlayers是选手总数,只要是偶数都能正常运行(你的场景是10人,完全没问题)。
额外优化提示
如果选手数量很多,可能会出现多次循环尝试的情况,这时候可以优化生成配对的逻辑,比如先固定一个选手的对手,再依次安排其他选手,减少重复尝试的次数,但对于10人这种小规模场景,上面的代码已经足够高效了。
内容的提问来源于stack exchange,提问作者Temporary-Failure
相关产品推荐
相关产品推荐

