加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在C 03和C 14的代码中进行简单随机混洗的最佳实践是什么?

发布时间:2020-12-16 09:55:50 所属栏目:百科 来源:网络整理
导读:背景:我正在为一个简单的游戏洗牌矢量元素.应该可以通过传递相同的整数种子来重复播放相同的游戏 – 反之亦然,不同的种子应该产生不同的游戏.加密安全性(或任何严格的安全性)不是设计目标;代码的清洁度是一个设计目标. C 98 / C 03引入了std :: random_shuf
背景:我正在为一个简单的游戏洗牌矢量元素.应该可以通过传递相同的整数种子来重复播放相同的游戏 – 反之亦然,不同的种子应该产生不同的游戏.加密安全性(或任何严格的安全性)不是设计目标;代码的清洁度是一个设计目标.

C 98 / C 03引入了std :: random_shuffle,使用如下:

int seed = ...;
std::srand(seed);  // caveat,see below

std::vector<int> deck = ...;
std::random_shuffle(deck.begin(),deck.end());

但是,从C 14开始,random_shuffle已被弃用(来源:N3924). C 14洗牌的方法是

int seed = ...;

std::vector<int> deck = ...;
std::shuffle(deck.begin(),deck.end(),std::mt19937(seed));

以下是减少每种方法的因素:

> srand / random_shuffle方式在C 14中已弃用,因此我们不应该使用它.
>在某些实现中,random_shuffle似乎不从srand中获取其种子,即,使用不同的值播种不会产生不同的输出! (Linux上的libstdc没有这个问题,但OSX 10.9.5上的Xcode确实如此.)
> shuffle / mt19937方式不是C 03的一部分,所以我们不能使用它.
> shuffle / mt19937方式似乎要求我们将种子一直传递到deck-shuffling代码中.对于我的应用程序,我更喜欢通过隐藏全局变量的srand等机制来“设置并忘记它”,而不是必须定义我自己的mt19937类型的全局PRNG.换句话说:我不想被PRNG的细节所困扰,我只是想改变我的载体!
>我有点担心线程安全(能够同时从不同的线程中移动两个不同的牌组),但显然不是同时关于线程安全和“可播种性”.认为线程安全是“很好的”.

我想到的第一个候选人是:

>咬住子弹并将int种子一直传递到deck-shuffling代码中(避免全局变量)
>使用像#if __cplusplus> = 20110000这样的东西来使用random_shuffle pre-C 11并随机播放后C 11
>在OSX上解决srand“bug”,使用random_shuffle的三参数版本和一些复杂的函子…这听起来很难看

第二位候选人是:

>螺丝C 03;只需删除任何不提供std :: shuffle和std :: mt19937开箱即用的实现

但有没有一些很好的方法来解决这个问题?我知道除非他们的程序是玩具程序否则没有人会有问题;但是必须有数以百计的玩具程序才能解决这个问题!

解决方法

即使在C 11中,分布在实现中也没有标准化.

编写自己的shuffler(对于每个元素,与另一个随机元素交换)和随机数生成器/分发.弱,慢随机数生成器简短而简单.

我会将你的’随机工厂’传递下来,并且可以在线程产生时“分叉”,因为这样做也可以让你在同一个执行中执行多次“运行”.拥有明确的状态而不是全局通常是值得的.但是如果单线程不需要:只需将随机工厂填入某个全局状态并抓住你的鼻子.

没有随机的随机播放将C 03连接到C 17,所以请用一个简短的手写一个.它还确保在多个平台上具有相同的行为,这有很多原因(测试覆盖率(在不同平台上相同),跨平台测试(OS / X上的错误可以在Windows上调试),无数东西的可移植性(保存游戏文件,基于io的网络游戏等)).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读