我在sql数据库中有一套测验游戏问题(实际上是javascript和sqlite)。这些问题都有难度级别从1到5,5最难。以下是数据的简化可视化......
+---------+--------------+ | id | difficulty | +---------+--------------+ | 1 | 1 | | 2 | 5 | | 3 | 2 | | 4 | 3 | | 5 | 2 | | 6 | 2 | | 7 | 4 | | 8 | 1 | | 9 | 5 | | 10 | 3 | +---------+--------------+
现在我可以在sql或代码中随机播放这些内容,这样它们就是一个没有重复的随机顺序,但我也想控制难度字段的排序方式。
因此,例如,我可以有一个改组的问题,其中难度级别顺序看起来像这样......
1,1,5,2,3,3,2,2,2,4
这有几个“困难”,这不是我想要的。玩游戏的用户将得到几组同样困难的问题。像这样的订单会更好......
1,2,3,2,5,4,1,2,3,2
我想确保问题被洗牌,但没有困难聚集。如果有任何“团块”,那么很少有困难。对MySQL / javascript(或PHP)的任何帮助都会很棒。
答案 0 :(得分:5)
不是将所有ID组合在一起,而是为什么不按难度对它们进行分组,然后将每个部分随机化,然后逐个将它们拉出来。或者,一旦它们被随机分类,您可以从随机难度中拉出它们,然后移除该难度级别,直到您有一个问题。
这是我在回答sje397时所考虑的问题,所以我会将其添加到我的答案中。
只要所有其他选择加起来最大的组减1,你就没有结块(假设你的算法是正确的)。然而,该算法基本上采取从A(具有最多选择数的组)中挑选的形式,从另一组中挑选,从A等中挑选,直到A等于其他组的大小。所以最好的算法会检查找到最大的组并从中挑选。然后它将从另一个组中选择,然后检查哪个组是最大的组,然后从中选择,除非它是之前选择的组等。
答案 1 :(得分:2)
以下策略在代码中如何:(以下是项目符号列表,但我无法在项目符号列表正确显示之后显示代码 - 我彻底厌恶本网站使用的“降价”垃圾)
难以订购问题
将问题分成两半,一个“简单”列表和一个“硬”列表
从简单和硬列表中逐一提问,在两者之间交替。 (这意味着在问题序列中你会有一个轻微到困难的小趋势,你可能会或可能不会这样。)
原始实施:
$resultset = your_preferred_query_function('SELECT id FROM question ORDER BY difficulty');
$questions_temp = array();
while ( $row = mysqli_fetch_assoc() ) {
$questions_temp[] = $row['id'];
}
if ( count($questions) % 2 ) {
$loop_limit = (count($questions) - 1) / 2;
$halfway = (count($questions) + 1) / 2;
$questions[0] = $questions_temp[$loop_limit];
} else {
$loop_limit = count($questions) / 2;
$halfway = count($questions) / 2;
$questions = array();
}
for ($i=0; $i<$loop_limit; $i++) {
$questions[] = $questions_temp[$i];
$questions[] = $questions_temp[$halfway+$i];
}
现在$questions
是一个数组,其中包含按照我的建议订购的问题。
答案 2 :(得分:1)
在一个真正随机的样本中,“clumps”做自然会出现。因此,如果您想删除这些内容,则必须手动执行某些操作,例如指定难度模式并选择匹配每个难度级别的随机问题
答案 3 :(得分:1)
通过随机调整的输入数组进行迭代,每当你点击一个与前一个元素具有相同难度级别的元素时,与下一个没有相同难度级别的元素交换。就在我脑海中,我认为这会将您的初始输入转换为:1,5,1,2,3,2,3,2,4,2
根据输入的不同,这种方法最终可能会导致结块,但可能还不够......
如果你的输入大于你需要的输入,你也可以删除任何与之前相同难度的元素。
答案 4 :(得分:0)
一个非常简单的解决方案(虽然效率不高)是:
<?php
define('MAX_QUESTIONS',10);
$dbh = new PDO("mysql:dbname=so;host=127.0.0.1","","");
$sql = "SELECT * FROM q group by difficulty order by rand()";
$data = $dbh->query($sql);
$rows = $data->fetchAll();
$ids = getIds($rows);
while (count($rows) < MAX_QUESTIONS ) {
$sql = "SELECT * FROM q where id not in ".
"(".join(",",$ids).") group by difficulty order by rand()";
$data = $dbh->query($sql);
$more_rows = $data->fetchAll();
$rows = array_merge($rows,$more_rows);
$ids = getIds($rows);
}
print_r($rows);
function getIds($data) {
$ids = array();
foreach ($data as $v) {
$ids[] = $v['id'];
}
return $ids;
}
?>
这是必需的,因为MySQL的组始终返回相同的ID,无论您之前是否订购过(即使在子查询中)。
关于这一点的好处是,它保证没有'团块'(以最后一个问题返回空的潜在成本会产生'丛集',但你可能会遇到特殊情况)
糟糕的是,您需要多个查询,并且rand()的排序非常低效,但如果您的表很小,那么它可能实际上并不重要。