游戏常用算法-洗牌算法

游戏常用算法-洗牌算法洗牌算法是一个比较常见的面试题。一副扑克54张牌,有54!种排列方式。最佳的洗牌算法,应该能够等概率地生成这54!种结果中的一种

大家好,又见面了,我是你们的朋友全栈君。

洗牌算法是一个比较常见的面试题。

一副扑克54张牌,有54!种排列方式。最佳的洗牌算法,应该能够等概率地生成这54!种结果中的一种

基于Unity的洗牌算法代码实现

GitHub链接

<span role="heading" aria-level="2">游戏常用算法-洗牌算法

抽牌洗牌

原理

这是完全合乎现实洗牌逻辑的算法。

就是抽出纸牌的最后一张随机插入到牌库中,这般抽54次就完成了对扑克牌的洗牌

复杂度

空间O(1),时间O(n^2)

优缺点

如果牌库是以一个数组描述,这种插入式的洗牌不可避免地要大量移动元素。

Fisher_Yates算法

原理

取两个列表,一个是洗牌前的序列A{1,2….54),一个用来放洗牌后的序列B,B初始为空

while A不为空

随机从A取一张牌加入B末尾

复杂度

空间O(n),时间O(n^2)

代码实现

 1 List<int> list = new List<int>(pukes.pukes);//洗牌前的序列A
 2 List<int> newlist = new List<int>(list.Count);//洗牌后的序列B
 3 for(int i = 0 ; i < pukes.pukes.Length ; ++i)
 4 {
 5   int randomIndex = Random.Range(0, list.Count);
 6   int r = list[randomIndex];//随机取牌
 7    newlist.Add(r);
 8    list.RemoveAt(randomIndex);
 9 }
10 pukes.ResetPuke(newlist.ToArray());//序列B为洗牌后的结果

优缺点

算法原理清晰,但额外开辟了一个List,而且为List删除元素是不可避免地需要移动元素

通过54次生成的随机数取1/54,1/53,…1/1能等概率地生成这54!种结果中的一种

Knuth_Durstenfeld算法

Knuth 和Durstenfeld 在Fisher 等人的基础上对算法进行了改进。 每次从未处理的数据中随机取出一个数字,然后把该数字放在数组的尾部, 即数组尾部存放的是已经处理过的数字 。 这是一个原地打乱顺序的算法,算法时间复杂度也从Fisher算法的 O ( n 2 )提升到了 O ( n )。

 

1 for(int i = pukes.pukes.Length - 1;i>0;--i)
2   {
3       int randomIndex = Random.Range(0, i+1);
4       pukes.Swap(randomIndex, i);
5   }

是最佳的洗牌算法

Inside_Out算法

C++ stl中random_shuffle使用的就是这种算法

原理

在[0, i]之间随机一个下标j,然后用位置j的元素替换掉位置i的数字

通过54次生成的随机数取1/1,1/2,…1/54能等概率地生成这54!种结果中的一种

复杂度

空间O(1),时间O(n)

代码实现

1 public static void Shuffle(Pukes pukes)
2   {
3       int len = pukes.pukes.Length;
4       for (int i = 0; i < len; ++i)
5       {
6           int randomIndex = Random.Range(0, i + 1);
7           pukes.Swap(i, randomIndex);
8       }
9   }

random_shuffle

关于c++ stl 的random_shuffle

它的算法原理和Knuth_Durstenfeld类似

先从所有元素中选一个与位置1的元素交换,然后再从剩下的n-1个元素中选择一个放到位置2,以此类推

参考链接

维基百科-Fisher–Yates shuffle

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155556.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • fsync、synchronous_commit 的简单测试

    fsync、synchronous_commit 的简单测试fsync(boolean)如果打开这个参数,PostgreSQL服务器将尝试确保更新被物理地写入到磁盘,做法是发出fsync()系统调用或者使用多种等价的方法(见wal_sync_method)。这保证了数据库集簇在一次操作系统或者硬件崩溃后能恢复到一个一致的状态。虽然关闭fsync常常可以得到性能上的收益,但当发生断电或系统崩溃时可能造成不可恢复的数据损坏。因此,只有在能很容易地从外部数据中重

    2022年5月31日
    38
  • 微信聊天内容制作生成器微信小程序源码/支持多种制作生成[通俗易懂]

    ☑️编号:ym205☑️品牌:小程序☑️语言:wx☑️大小:345KB☑️类型:聊天内容制作☑️支持:小程序????欢迎免费领取(注明编号)????✨源码介绍这是一款微信聊天内容制作生成小程序源码,该小程序支持制作多种内容。支持单人聊天模式制作,支持群聊模式制作生成;每一种模式都支持我们微信需要的功能都有,视频,语音,时间,内容等等,大家可以最后看演示图!!另外还支持微信零钱,也就是我的界面制作生成DIY金额(具体大家看演示图);另外也支持微信红包制作DIY金额,发

    2022年4月9日
    173
  • jmeter并发测试教程_jmeter高并发测试

    jmeter并发测试教程_jmeter高并发测试BeanShellSamplerBeanShellSampler我们添加一个beanshellsample,用java脚本将文件保存到本地注意:文件保存路径如果写成:C:\Users\feng\Desktop,会报错"TokenParsingError:Lexicalerror"正确格式:C:/Users/feng/De…

    2022年9月29日
    0
  • 微服务 数据同步_微服务session共享怎么实现

    微服务 数据同步_微服务session共享怎么实现微服务之数据同步Porter

    2022年4月21日
    103
  • 3G标准中的TDD与FDD模式

    3G标准中的TDD与FDD模式2000年5月5日,在土耳其举行的ITU-R全会上,通过了包括中国提案在内的五种无线传输技术的规范,渲腥只贑DMA技术,两种基于TDMA技术。  (1)基于CDMA的技术规范  IMT-2000CDMADS(WCDMA、cdma2000DS)IMT-2000CDMATDD(TD-SCDMA、TD-CDMA)  (2)基于TDMA技术的技术规范  IMT-2000CDMASC(u

    2022年5月11日
    40
  • cglib代理[通俗易懂]

    cglib代理[通俗易懂]cglib代理​ 在此之前,我们学习了JDK动态代理,而JDK动态代理有一定的局限性,因为使用JDK动态代理时,被代理类必须实现接口,然后动态代理生成的代理类同时实现该接口实现代理模式,但在特定情况下没办法让被代理类实现接口,那么此时我们就需要使用cglib代理。代理模式的三要素两个成员:被代理对象、执行者(类似于Spring中切面的概念)使用场景:当某件事情不方便自己做,但是必须要做时…

    2022年5月6日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号