我正在尝试创建一些逻辑来生成double-elimination tournament bracket中的事件计划.
以下是一个示例8团队支架:
rd1 quarter semi finals
A───┐
0 ├───────A┐
B───┘ │
4 ├────────A┐
C───┐ │ │
1 ├───────C┘ │
D───┘ │
10 ├──────A┐
E───┐ │ │
2 ├───────E┐ │ │
F───┘ │ │ │
5 ├────────E┘ │
G───┐ │ 13 ├───= Champ
3 ├───────G┘ │
H───┘ │
E────┐ │
C───┐ │ │
B───┐ 8 ├────C┐ 12 ├────E┘
6 ├B───┘ │ │
D───┘ 11 ├C────┘
G───┐ │
F───┐ 9 ├────G┘
7 ├F───┘
H───┘
数字代表匹配数组中的索引,这是所需的输出.例如,索引0将代表第1组与第8组(使用种子系统),索引4将代表索引0的获胜者与索引1的获胜者.
失败者的支架来自赢家支架的输家,其中指数6是指数0的输家与指数1的输家,指数8是指数4的输家与指数6的赢家.
在视觉示例中,您可以看到按字母标记的团队,并且每次都显示获胜团队在顶部分支上的明确示例,并且失败团队位于底部分支上.指数0代表A队与B队,指数4代表指数0(A)与指数1(C)的胜者的胜者.指数6是指数0(B)与指数1(D)的输家的输家,指数8是指数4(C)与指数6(B)的赢家的输家
有一个明显的模式出现了,但是当我尝试适应不同数量的竞争对手时,我的逻辑变得混乱和混乱.为了简单起见,我将支架修改为只有2个团队的力量.我能够编写所有内容来为8个团队创建一个匹配数组,但是我对自己的代码感到迷茫,因为它似乎不具备可扩展性.
// round one
for( $i = 0; $i < log( count( $competitors ), 2 ); $i++ )
{
$seeded = array( );
foreach( $competitors as $competitor )
{
$splice = pow( 2, $i );
$seeded = array_merge( $seeded, array_splice( $competitors, 0, $splice ) );
$seeded = array_merge( $seeded, array_splice( $competitors, -$splice ) );
}
$competitors = $seeded;
}
$events = array_chunk( $seeded, 2 );
// quarter finals
for( $i = 0; $i < count( $competitors ) / 2; $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i, 'from_event_rank' => 1 ), // rank 1 = winner
array( 'from_event_index' => ++$i, 'from_event_rank' => 1 )
) );
}
$round_matchups = array( );
for( $i = 0; $i < count( $competitors ) / 2; $i++ )
{
array_push( $round_matchups, array(
array( 'from_event_index' => $i, 'from_event_rank' => 2 ), // rank 2 = loser
array( 'from_event_index' => ++$i, 'from_event_rank' => 2 )
) );
}
$events = array_merge( $events, $round_matchups );
for( $i = 0; $i < count( $round_matchups ); $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i + count( $competitors ) / 2, 'from_event_rank' => 2 ),
array( 'from_event_index' => $i + count( $competitors ) / 2 + count( $competitors ) / 2 / 2, 'from_event_rank' => 1 )
) );
}
// semi finals
for( $i = 0; $i < count( $competitors ) / 2 / 2; $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i + count( $competitors ) / 2, 'from_event_rank' => 1 ),
array( 'from_event_index' => ++$i + count( $competitors ) / 2, 'from_event_rank' => 1 )
) );
}
$round_matchups = array( );
for( $i = 0; $i < count( $competitors ) / 2 / 2; $i++ )
{
array_push( $round_matchups, array(
array( 'from_event_index' => $i + count( $competitors ), 'from_event_rank' => 1 ),
array( 'from_event_index' => ++$i + count( $competitors ), 'from_event_rank' => 1 )
) );
}
$events = array_merge( $events, $round_matchups );
for( $i = 0; $i < count( $round_matchups ); $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i + count( $competitors ) + count( $competitors ) / 2 - 2, 'from_event_rank' => 2 ),
array( 'from_event_index' => $i + count( $competitors ) + count( $competitors ) / 2 - 1, 'from_event_rank' => 1 )
) );
}
// finals
for( $i = 0; $i < count( $competitors ) / 2 / 2 / 2; $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i + count( $competitors ) / 2 * 3 - 2, 'from_event_rank' => 1 ),
array( 'from_event_index' => ++$i + count( $competitors ) / 2 * 3 - 1, 'from_event_rank' => 1 )
) );
}
输出上面的代码:
$events = array(14) {
[0]=>
array(2) {
[0]=>
array(4) {
["team"]=>int(1)
}
[1]=>
array(4) {
["team"]=>int(8)
}
}
[1]=>
array(2) {
[0]=>
array(4) {
["team"]=>int(4)
}
[1]=>
array(4) {
["team"]=>int(5)
}
}
[2]=>
array(2) {
[0]=>
array(4) {
["team"]=>int(2)
}
[1]=>
array(4) {
["team"]=>int(7)
}
}
[3]=>
array(2) {
[0]=>
array(4) {
["team"]=>int(3)
}
[1]=>
array(4) {
["team"]=>int(6)
}
}
[4]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(0)
["from_event_rank"]=>int(1)
}
[1]=>
array(2) {
["from_event_index"]=>int(1)
["from_event_rank"]=>int(1)
}
}
[5]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(2)
["from_event_rank"]=>int(1)
}
[1]=>
array(2) {
["from_event_index"]=>int(3)
["from_event_rank"]=>int(1)
}
}
[6]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(0)
["from_event_rank"]=>int(2)
}
[1]=>
array(2) {
["from_event_index"]=>int(1)
["from_event_rank"]=>int(2)
}
}
[7]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(2)
["from_event_rank"]=>int(2)
}
[1]=>
array(2) {
["from_event_index"]=>int(3)
["from_event_rank"]=>int(2)
}
}
[8]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(4)
["from_event_rank"]=>int(2)
}
[1]=>
array(2) {
["from_event_index"]=>int(6)
["from_event_rank"]=>int(1)
}
}
[9]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(5)
["from_event_rank"]=>int(2)
}
[1]=>
array(2) {
["from_event_index"]=>int(7)
["from_event_rank"]=>int(1)
}
}
[10]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(4)
["from_event_rank"]=>int(1)
}
[1]=>
array(2) {
["from_event_index"]=>int(5)
["from_event_rank"]=>int(1)
}
}
[11]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(8)
["from_event_rank"]=>int(1)
}
[1]=>
array(2) {
["from_event_index"]=>int(9)
["from_event_rank"]=>int(1)
}
}
[12]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(10)
["from_event_rank"]=>int(2)
}
[1]=>
array(2) {
["from_event_index"]=>int(11)
["from_event_rank"]=>int(1)
}
}
[13]=>
array(2) {
[0]=>
array(2) {
["from_event_index"]=>int(10)
["from_event_rank"]=>int(1)
}
[1]=>
array(2) {
["from_event_index"]=>int(12)
["from_event_rank"]=>int(1)
}
}
}
关于我如何修改它以适用于4人团队,16人团队或2 ^ n团队支架的任何想法?我觉得“半决赛”标题下的逻辑应重复0次,但每次我尝试根据总轮数循环它时,它只重复与前一轮相同的匹配.
解决方法:
好吧,我一直在跋涉现有的逻辑,并能够为4,8,16和32团队双重消除括号生成时间表.逻辑不是必须简洁的,但至少可以让我理解发生了什么.在将来,我希望稍微修改和清理它,但是现在必须这样做.
$rounds = log( count( $competitors ), 2 ) + 1;
// round one
for( $i = 0; $i < log( count( $competitors ), 2 ); $i++ )
{
$seeded = array( );
foreach( $competitors as $competitor )
{
$splice = pow( 2, $i );
$seeded = array_merge( $seeded, array_splice( $competitors, 0, $splice ) );
$seeded = array_merge( $seeded, array_splice( $competitors, -$splice ) );
}
$competitors = $seeded;
}
$events = array_chunk( $seeded, 2 );
if( $rounds > 2 )
{
$round_index = count( $events );
// second round
for( $i = 0; $i < count( $competitors ) / 2; $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i, 'from_event_rank' => 1 ), // rank 1 = winner
array( 'from_event_index' => ++$i, 'from_event_rank' => 1 )
) );
}
$round_matchups = array( );
for( $i = 0; $i < count( $competitors ) / 2; $i++ )
{
array_push( $round_matchups, array(
array( 'from_event_index' => $i, 'from_event_rank' => 2 ), // rank 2 = loser
array( 'from_event_index' => ++$i, 'from_event_rank' => 2 )
) );
}
$events = array_merge( $events, $round_matchups );
for( $i = 0; $i < count( $round_matchups ); $i++ )
{
array_push( $events, array(
array( 'from_event_index' => $i + count( $competitors ) / 2, 'from_event_rank' => 2 ),
array( 'from_event_index' => $i + count( $competitors ) / 2 + count( $competitors ) / 2 / 2, 'from_event_rank' => 1 )
) );
}
}
if( $rounds > 3 )
{
// subsequent rounds
for( $i = 0; $i < $rounds - 3; $i++ )
{
$round_events = pow( 2, $rounds - 3 - $i );
$total_events = count( $events );
for( $j = 0; $j < $round_events; $j++ )
{
array_push( $events, array(
array( 'from_event_index' => $j + $round_index, 'from_event_rank' => 1 ),
array( 'from_event_index' => ++$j + $round_index, 'from_event_rank' => 1 )
) );
}
for( $j = 0; $j < $round_events; $j++ )
{
array_push( $events, array(
array( 'from_event_index' => $j + $round_index + $round_events * 2, 'from_event_rank' => 1 ),
array( 'from_event_index' => ++$j + $round_index + $round_events * 2, 'from_event_rank' => 1 )
) );
}
for( $j = 0; $j < $round_events / 2; $j++ )
{
array_push( $events, array(
array( 'from_event_index' => $j + $total_events, 'from_event_rank' => 2 ),
array( 'from_event_index' => $j + $total_events + $round_events / 2, 'from_event_rank' => 1 )
) );
}
$round_index = $total_events;
}
}
if( $rounds > 1 )
{
// finals
array_push( $events, array(
array( 'from_event_index' => count( $events ) - 3, 'from_event_rank' => 1 ),
array( 'from_event_index' => count( $events ) - 1, 'from_event_rank' => 1 )
) );
}
我已经验证了最多32支队伍的结果(仅2的权力),并且能够生成64个团队的计划,这似乎是正确的.有时候,持久性会得到回报.