php洗牌一包卡片

Geo*_*off 5 php string random shuffle permutation

我想用php创建一个随机桥手的集合.我认为我可以编码一个有序的卡片组作为$deal下面的字符串(我喜欢在考虑大小写时有52个字母).我发现了php函数str_shuffle.所以我认为我可以做到以下几点:

$pack = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$shuffledPack = str_shuffle($pack);
Run Code Online (Sandbox Code Playgroud)

这给了我想要的输出.

我的问题是:确实str_shuffle为每个可能的排列提供均匀分布的输出吗?

Ja͢*_*͢ck 4

在内部,str_shuffle()使用rand()不会产生高质量的随机数,正如您在这个答案中看到的那样;如果您想要更好的分布,您可能希望自己实现 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;
}
Run Code Online (Sandbox Code Playgroud)

另请参阅我之前关于寻找合适的 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);
    // ...
}
Run Code Online (Sandbox Code Playgroud)