php洗牌一包卡片

时间:2014-07-02 14:31:56

标签: php string random permutation shuffle

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

$pack = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$shuffledPack = str_shuffle($pack);

这给了我想要的输出。

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

1 个答案:

答案 0 :(得分:4)

在内部,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);
    // ...
}