我想用 php 创建随机桥牌的集合。我认为我可以将一副有序的纸牌编码为下面的字符串 $deal
(考虑到大写和小写时,我喜欢它有 52 个字母)。我发现了 php 函数 str_shuffle
。所以我想我可以做到以下几点:
$pack = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$shuffledPack = str_shuffle($pack);
这给了我想要的输出。
我的问题是:str_shuffle
是否为每个可能的排列提供遵循均匀分布的输出?
最佳答案
在内部,str_shuffle()
使用 rand()
,它不会产生高质量的随机数,正如您在 this answer 中看到的那样;如果您想要更好的分布,您可能希望自己实现 Fisher-Yates 并选择您选择的随机来源,例如mt_rand()
:
function my_str_shuffle($str)
{
if ($str == '') {
return $str;
}
$n_left = strlen($str);
while (--$n_left) {
$rnd_idx = mt_rand(0, $n_left);
if ($rnd_idx != $n_left) {
$tmp = $str[$n_left];
$str[$n_left] = $str[$rnd_idx];
$str[$rnd_idx] = $tmp;
}
}
return $str;
}
另见 my earlier answer寻找合适的 0/1 随机化器。
更新
使用 openssl_random_pseudo_bytes()
作为你的随机来源:
assert($n_left <= 255);
$random = openssl_random_pseudo_bytes($n_left);
while (--$n_left) {
$rnd_index = round($random[$n_left] / 255 * $n_left);
// ...
}
关于php 洗牌,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24533869/