关于C语言中的随机数及扑克游戏发牌随机算法的一点疑惑

逍遥书生 发布于 2012/11/14 10:17
阅读 2K+
收藏 1
我仅仅是一个C语言爱好者,虽然爱好了好几年,但是一些简单的代码写起来很费劲,读仅仅几十行的代码还勉强可以。


我在读C语言学习参考书的时候,看到作者的实际例子,一个二十一点游戏,我很想自己改写一下。原因就是他的发牌算法让我觉得不是很理想。
涉及到发牌,就需要随机算法,随机数。但是C语言提供的随机函数srand,rand只是伪随机函数。srand会提供一个种子,rand根据种子产生一个固定的数列。只要种子相同,这个数列就相同。简单的随机就是每次调用rand时,使用一个不一样的种子,一般情况下,srand使用time的返回值产生种子。但是这样有一个缺陷,time函数的数量级是秒,要是你理解有歧义的话,可以认为系统时间至少变换一秒,time的返回值才会改变。你第一次使用time给你一个返回值,然后0.1秒后time的返回值还是同一个值。那么rand的结果其实是一样的。


为此我设想弄一个更好点的随机算法,我想了个方案。


首先,用一个种子产生一个数组a,这个数组的取值范围很大,然后换种子使用rand产生一个取值范围在需求范围值的数组b,用a[0]与b[0]取余作为真正的随机数,以此类推。不过最后的结果很失败,明显偏离太多。
后来改了一下,用一个种子产生一个符合取值范围的数组,假设为a[20]。然后换种子使用rand产生一个在1到20之间的数b,然后提取a[b-1]作为真正的随机数字使用,然后循环产生数列。
我不知道这样的数是否更能体现随机性。因为我看到C语言的库函数源码就很头大,不知道rand的原理,了解的深刻的高手可否说说。


以上是关于随机数,下面是扑克游戏中的发牌算法的疑惑。


原作者的发牌原理介绍一下,先定义一个数组a[54],赋值a[0]为1,a[1]为2,以此类推。第一轮,随机获得一个0到53的数i,把a[i]发出去,然后把a[53]赋值给a[i]。第二轮随机获得一个0到52的数i,把a[i]发出去,然后把a[52]赋值给a[i]。如此循环发牌。
根据发出的a[i],确定花色和点数。比如1到13为黑桃1到A,14到26为红桃1到A。


这个可以说能作为扑克游戏的发牌算法,但是心里感觉还是有点怪怪的。因为原作者的程序中只有你摸牌才执行一次循环,就感觉每次摸牌都要洗一次牌差不多。
我最后改了一下,就是先把牌洗好。
另外定义一个数组,每次发出的牌依次存进数组里面,循环完成后,开始摸牌,从头到尾依次取数组的值。
我不知道这样改是否多此一举,或者谁能提供一个更好点的发牌算法?

加载中
0
match5
match5
你用clock()来生成种子 clock()返回的cpu时钟
0
逍遥书生
逍遥书生

引用来自“MatchZ”的答案

你用clock()来生成种子 clock()返回的cpu时钟
谢谢
0
match5
match5

引用来自“逍遥书生”的答案

引用来自“MatchZ”的答案

你用clock()来生成种子 clock()返回的cpu时钟
谢谢
关于洗牌的问题    恰好看到篇帖子 http://coolshell.cn/articles/8593.html 应该对你有帮助
0
逍遥书生
逍遥书生

引用来自“MatchZ”的答案

引用来自“逍遥书生”的答案

引用来自“MatchZ”的答案

你用clock()来生成种子 clock()返回的cpu时钟
谢谢
关于洗牌的问题    恰好看到篇帖子 http://coolshell.cn/articles/8593.html 应该对你有帮助
我看了一下你说的那个帖子,大意是说随机数其实不够随机的问题。这个问题以我自己的水平还真的很难,我先自己测试一下我的程序吧。我在另外发个我洗牌的完整代码。
0
逍遥书生
逍遥书生
那个帖子的楼主的洗牌原理是平分,交叉穿插,这个对我有启发。我的洗牌算法及其简单就是rand取模。
返回顶部
顶部