【问题标题】:PHP Single Elimination Tournament TablePHP单淘汰赛桌
【发布时间】:2018-07-11 18:47:13
【问题描述】:

我浏览了其他几篇与此类似的帖子,但找不到任何适合我正在寻找的内容...

我已经设法硬编码了一个 8 支球队锦标赛括号表,但我真的想要一种方法来根据输入的球队数量使用 for/if 语句来绘制表格。

这是使用 colspans 和 rowspans 对表格进行硬编码以创建空格的代码(在您说使用 CSS 而不是表格之前,我不太了解 CSS,但对表格很有信心):

<table border='1' cellspacing='1' cellpadding='1'>
<tr><td colspan='2' width='120'><b>Round 1</b></td></td><td colspan='2' width='120'><b>Round 2</b></td></td><td colspan='2' width='120'><b>Final</b></td><td width='120'><b>Winner</b></td></tr>
<tr><td colspan='2'>&nbsp;</td><td colspan='2' rowspan='2'></td><td colspan='2' rowspan='4'></td><td rowspan='8'></td></tr>
<tr><td>Group 1</td><td width='20'></td></tr>
<tr><td align='center'>Score 1</td><td></td><td>Round 1 Winner</td><td width='20'></td></tr>
<tr><td>Group 2</td><td></td><td rowspan='3' align='center'>Score 5</td><td></td></tr>
<tr><td colspan='2'></td><td></td><td>Round 2 Winner</td><td width='20'></td></tr>
<tr><td>Group 3</td><td></td><td></td><td rowspan='7' align='center'>Score 7</td><td></td></tr>
<tr><td align='center'>Score 2</td><td></td><td>Round 1 Winner<td></td><td></td></tr>
<tr><td>Group 4</td><td></td><td colspan='2' rowspan='3'></td><td></td></tr>
<tr><td colspan='2'></td><td></td><td>Champion</td></tr>
<tr><td>Group 5</td><td></td><td></td><td rowspan='8'></td></tr>
<tr><td align='center'>Score 3</td><td></td><td>Round 1 Winner</td><td></td><td></td></tr>
<tr><td>Group 6</td><td></td><td rowspan='3' align='center'>Score 6</td><td></td><td></td></tr>
<tr><td colspan='2'></td><td></td><td>Round 2 Winner</td><td></td></tr>
<tr><td>Group 7</td><td></td><td></td><td colspan='2' rowspan='3'></td></tr>
<tr><td align='center'>Score 4</td><td></td><td>Round 1 Winner</td><td></td></tr>
<tr><td>Group 8</td><td></td><td colspan='2'></td></tr>
</table>

这是它产生的:

到目前为止,这是我使用 for 和 if 语句创建上述内容的尝试,我已经到了在第一列中列出团队名称的地步,但我无法确定我需要做什么点...

<?php
echo "<table border='1' cellspacing='1' cellpadding='1'>";
$num_teams = 8;
$nRounds = floor(log($num_teams,2));
$max_rows = $num_teams*2;
for ($row = 0; $row <= $max_rows; $row++)
{
    echo "<tr>";
    if ($row == 0)
    {
        for ($i = 1; $i <= $nRounds+1; $i++)
        {
            if($i < $nRounds)
            {
                echo "<td width='120'><b>Round ".$i."</b></td>";
                echo "<td width='20'></td>";
            }
            elseif($i == $nRounds)
            {
                echo "<td width='120'><b>Final</b></td>";
                echo "<td width='20'></td>";
            }
            else
            {
                echo "<td width='120'><b>Winner</b></td>";
            }
        }       
    }
    elseif($row == 1)
    {
        $rowwhitespace = ($nRounds*2)+1;
        echo "<td colspan='".$rowwhitespace."'>&nbsp;</td>";
    }
    else
    {
        $rowwhitespace = ($nRounds*2);
        for ($i = 1; $i <= $num_teams; $i++)
        {
            if($i == $row/2)
            {
                echo "<td>Group ".$i."</td>";
                echo "<td colspan='".$rowwhitespace."'></td>";
            }
        }
    }
    echo "</tr>";
}
echo "</table>";
?>

这就是它的样子:

最终,团队名称、分数和获胜者将从数据库中提取,因此一旦我能够正确布局结构,就需要将其合并。

我还希望它可以扩展到 64 个团队,并根据这么多团队自动绘制表格,而无需使用手动硬编码表格,因为为 16,32 和 64 个团队创建表格需要很长时间。再加上考虑对多达 64 个团队进行双重淘汰,这将使手动编码这项艰巨的工作!

对此的任何指示或帮助将不胜感激!

【问题讨论】:

  • 不是关于您的问题,但您不需要所有这些回声,只需将该 html 放在页面上。
  • 公平评论,谢谢,已编辑。
  • 我认为这绝对是学习 CSS 的一个理由,因为他们可以用很少的几行代码解决这个问题。

标签: php html-table


【解决方案1】:

编辑:

好的,我决定在凌晨 2 点之前解决这个问题。调试大约花了半个小时。我知道我没有更多的跨越,但我不想再花时间尝试做到这一点,因为它需要更多地调整数学公式以正确获得这些公式。截图如下。如果您需要任何解释,请告诉我。

<?php

function is_player($round, $row, $team) {
    return $row == pow(2, $round-1) + 1 + pow(2, $round)*($team - 1);
}

$num_teams = 16;
$total_rounds = floor(log($num_teams, 2)) + 1;
$max_rows = $num_teams*2;
$team_array = array();
$unpaired_array = array();
$score_array = array();

for ($round = 1; $round <= $total_rounds; $round++) {
    $team_array[$round] = 1;
    $unpaired_array[$round] = False;
    $score_array[$round] = False;
}


echo "<table border=\"1\" cellspacing=\"1\" cellpadding=\"1\">\n";
echo "\t<tr>\n";

for ($round = 1; $round <= $total_rounds; $round++) {

    echo "\t\t<td colspan=\"2\"><strong>Round $round</strong></td>\n";

}

echo "\t</tr>\n";

for ($row = 1; $row <= $max_rows; $row++) {

    echo "\t<tr>\n";

    for ($round = 1; $round <= $total_rounds; $round++) {
        $score_size = pow(2, $round)-1;
        if (is_player($round, $row, $team_array[$round])) {
            $unpaired_array[$round] = !$unpaired_array[$round];
            echo "\t\t<td>Team</td>\n";
            echo "\t\t<td width=\"20\">&nbsp;</td>\n";
            $team_array[$round]++;
            $score_array[$round] = False;
        } else {
            if ($unpaired_array[$round] && $round != $total_rounds) {
                if (!$score_array[$round]) {
                    echo "\t\t<td rowspan=\"$score_size\">Score</td>\n";
                    echo "\t\t<td rowspan=\"$score_size\" width=\"20\">$round</td>\n";
                    $score_array[$round] = !$score_array[$round];
                }
            } else {
                echo "\t\t<td colspan=\"2\">&nbsp;</td>\n";
            }
        }

    }

    echo "\t</tr>\n";

}

echo "</table>\n";

?>

干杯


原文: 我没有时间编写脚本,但从数学上讲,它应该遵循某种模式。如果你假设球队总是 2 的力量(所以你总是可以有一个冠军)和 4 排在开始第一轮开始所以你有

1| Empty Row
2| Team 1
3|    Score
4| Team 2

那么我们可以在数学上得出以下结论:

$round 为轮数,$row 为行号,$team 为该轮的团队号(稍后会解释)。

团队打印在$row = [2^($round-1) + 1] + [2^($round)]*$team 上,要理解这个公式,您需要将其绘制出来,但基本上因为团队是 2 的幂,并且您使用 4 行(2 的幂)来表示第一轮,我们可以不断地将事情分解并以数学方式求解打印团队的行#。所以公式指出,对于编号为$team 的球队,$round 将列在行$row 中,因为一半的球队被淘汰,所以球队的数量总是除以 2。正如您在代码中所做的那样,总轮数只是团队总数的 2 个基数。下一个分数会在每对团队之间发布,因此确定还不错。

当然,最大的问题是您需要打印一个表格,该表格在打印时需要按行而不是按列。最好的方法是有一个目标公式,然后测试你所在的行和列是否满足只需要一个简单函数来测试的方程(当你生成你知道的列总数时,因为你知道有多少回合)。

我希望这有助于引导您实现我试图设定的目标。如果我有时间,我会尝试稍后做点什么。干杯。

【讨论】:

  • 方括号在 $row 等式中的作用是什么?
  • 对不起,我把它写得更像是一个等式,用代码语言,我想它会搞砸了,但这只是为了在逻辑上强调不同的部分。真的,你可以对它造成的任何混乱感到抱歉。
  • 好的,使用该公式(用普通括号替换方括号)不会给出正确的行号,例如:如果 Round = 1 和 Team = 1,则行号返回为 4应该是 2。假设该行从零开始,然后是一个间隙行。
  • 哦,是的,erp 很抱歉,我很快就抵消了它应该是 $row = (2^($round-1) + 1) + (2^($round))*( $team - 1)
  • 好的,太好了,现在这可以完美地在所有回合中输出正确的行,以显示团队名称应该输出到的位置,包括获胜者。现在只需要开发这个来绘制表格。
【解决方案2】:

最快和最简单的方法是将您手动编码的 html 保存到某种模板文件中。比如说tournament-table.html

接下来,将保存的模板文件中的动态数据的每个实例更改为模板标签,例如:

  • 第 1 组 => {#group1-name}
  • 第 2 组 => {#group2-name}
  • 得分 1 => {#score1-name}
  • 冠军 => {#champion-name}

您的模板看起来像这样:

<tr><td>{#group1-name}</td><td width='20'></td></tr>
<tr><td align='center'>{#score1-name}</td><td></td><td>{#round1-winner}</td><td width='20'></td></tr>

接下来,要填写数据,您只需将模板加载到变量中并对其进行字符串替换:

  • 要加载数据,请执行以下操作:

    $raw_template = file_get_contents('/path/to/your/template/tournament-table.html');
    
  • 将需要的数据填入变量中:

    //do the needed queries
    //after that, fill variable with query and processes result
    $group1_name = "Group 1";
    $group2_name = "Group 2";
    $Score1_name = "Score 1";
    
  • 下一步是执行字符串替换:

    $raw_template = str_replace('{#group1-name}', $group1_name, $raw_template, 1);
    
  • 最后,回显结果:

    echo $raw_template;
    

【讨论】:

  • 有趣的方法,意味着必须为大量团队手动创建表格,但仍有可能。
猜你喜欢
  • 2013-05-16
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
  • 2012-02-18
相关资源
最近更新 更多