Algorithm 我什么时候应该编写自己的随机数算法而不是使用股票数学函数?
因此,我正在Lua中进行脚本测试,我被问到以下问题:Algorithm 我什么时候应该编写自己的随机数算法而不是使用股票数学函数?,algorithm,random,lua,Algorithm,Random,Lua,因此,我正在Lua中进行脚本测试,我被问到以下问题: 创建一个算法来生成一副牌,1-52。洗牌牌(不要使用类似array.randomize()的东西)。然后将5张牌分发给两个不同的玩家。因为每张牌一次必须发给不同的玩家 通常我会这样做来得到一个随机数 local newDeck = {} --assume this array has all 52 cards in a playing deck math.randomseed( os.time() ) local card = math.ra
local newDeck = {} --assume this array has all 52 cards in a playing deck
math.randomseed( os.time() )
local card = math.random(#newDeck)
…但问题似乎是特别要求我不要使用股票数学函数
(不要使用类似于array.randomize()的东西)
这样做有什么好处?我无法想象这样一个游戏的玩家会注意到随机和伪随机之间的区别。如果它这么简单的话。作为语言一部分的大多数随机数生成器都是线性同余生成器,这意味着下一个术语
J
与前一个术语I
相关
J = (aI + b) mod c
其中,a
,b
,c
是常数
这意味着可以从一位数的术语中破译序列(这是一组联立方程组,在处理模数时有点技巧)
我想说,一个精明的玩家一定会注意到你的序列的伪随机性,甚至可能通过取消你的生成器来玩这个系统。你需要使用更复杂的方案。(早期的尝试包括Park Miller和Bays Durham;相当有名的方法)。我相信欢迎您使用内置随机数生成器获取随机数,但禁止使用任何可能存在的内置阵列洗牌器。您如何使用rng使每张牌在每个位置的可能性相等?您只需写一些东西,抽取一张随机牌并将其放入洗牌组:
function shuf(tab)
local new = {}
for k=1,#tab do
new[#new+1]=table.remove(tab,math.random(#tab))
end
end
这种方法确保你没有替身
我真的不认为使用不同的RNG会有那么大的影响,除非你在做密码学或其他真正重要的事情
解释问题:只是不要使用为此编写的库函数。但是洗牌器和随机数生成器之间有区别,因为后者可以返回双倍值,而前者不能。我不确定你在最后一部分中问的是什么,因为计算机无法真正创建某种意义上非伪随机的东西。事实上,人类是否能做到这一点是有争议的(它涉及到整个命运/命运的事情…深层次的东西)。这个问题听起来像你应该使用股票随机函数,而不是洗牌部分。这一点是为了让您了解如何洗牌数组(提示:Fisher-Yates)以获得更实际的答案:大多数标准库中包含的PRNG都很糟糕。因此,每当您需要高质量的随机性时,您都需要将其替换为一个像样的实现。对于在线游戏,你甚至需要使用加密PRNG,因为其他玩家可能会作弊。@ShashankGupta-你是对的。这句话措词不当。这都是伪随机的。我应该说一下自定义随机化算法和lua库随机化器之间的区别。@CodesInChaos-很高兴知道。我甚至没有意识到有加密PRNG这样的东西,我会尝试Fisher-Yates…但是如果我的随机种子是基于系统时钟的,玩家难道不需要一只眼睛盯着时钟并注意到当前时间和15张卡之间的连接才能注意到它是伪的吗?我仍然无法想象这会发生。@PHazer说这是可能的。有人为口袋妖怪游戏破解任天堂DS时钟,滥用RNG获得闪亮的口袋妖怪(他们出现的机会非常少,但已经有程序从生成器中计算种子并预测未来的数字)。这些程序根据用户输入的时间工作,即启动口袋妖怪游戏的时间。“这真的取决于某人对你的游戏有多热衷。”沙尚古普塔说得对,但NDS的时钟精度仅为秒,而不是毫秒。我并不是说这是不可能的,只是说任天堂把他们的实现搞砸了,让它变得比应该的更可利用。