开发笔记:基于积分的游戏排行榜实现方式探讨
竞技场往往是游戏中不可缺少的系统,根据不同的需求类型,竞技场排行榜的类型可以有如下划分:
1.按照排名更新的方式划分:依靠积分进行排行的竞技场,当玩家完成挑战后根据一定的规则进行双方积分的增减,依据新的积分进行重新排名;不依靠积分进行排行的竞技场,只有当排名较低玩家战胜了排名较高玩家时,会交换双方排名。前者一次积分变化会导致较多的玩家排名发生变动,后者一次最多只会影响两名玩家的排名,但要考虑相同玩家同时被挑战的情况。
2.按照排行是否严格划分:并列排行榜允许积分相同的玩家处于同一名次,严格排行榜需要处理玩家相同积分情况下决定排名的规则。
此处我们只讨论积分排行榜。
积分排行榜的关键在于对于一个有序数据结构的维护更新,而对于该数据结构的实现主要有两种思路:
1.自己使用语言实现有序的数据结构
2.借助现成的工具,如MySQL,Redis实现有序排序
自己制定数据结构的方法
1.有序列表
按照积分大小将列表进行排序。
查询TopN:只需获取列表前TopN个元素,时间复杂度O(1)。
查询指定玩家排名:计算积分大于该玩家的人数,时间复杂度O(n)。
更新排名:玩家积分发生变化,需要将旧元素删除,把积分变化后的新元素插入列表中并进行重新排序,若使用快速排序,则时间复杂度为O(n²)。不过大多数情况下列表是基本有序的,比起对单纯打乱的列表进行排序会好很多。
排行榜较小,对效率没有极端要求的时候可以使用这种方法。
2.数组
构建大小为M的数值rank[],此时积分s对应的排名为rank[s]。
查询TopN:获取列表rank[1:N]的元素即可。
查询玩家自己排名:查询积分s对应的排名直接查询rank[s]即可,时间复杂度O(1)。
更新:若用户积分从s变为s+n,则把rank[s]到rank[s+n-1]这n个元素值加1即可,时间复杂度为O(n)。
很明显,游戏中排行榜积分相同的情况并不少见,引入桶可以解决积分相同的情况,但积分更新和查询玩家自身排行的策略需要改变,改变之后的策略可能并不比有序列表效率高。
3.平衡二叉树(AVL)
查询TopN:获取树的前N个元素即可,时间复杂度O(1)。
查询自己的排名:需要对数进行遍历,找出积分高于自己的玩家数量,时间复杂度O(n)。
更新:需要将原元素删除,将新元素插入树中,时间复杂度O(logn)。
4.跳表(skiplist)
跳表本质是可以实现二分查找的有序链表。
个人了解不深,直接给出参考文章:
https://yuerblog.cc/2019/02/13/skiplist-rank/
感觉在计算个人排名的时候效率会比平衡二叉树高,其他地方与平衡二叉树相差不大。
5.树形分区算法
详见
https://cloud.tencent.com/developer/article/1621522
本质是平衡二叉树,但与上面单纯使用平衡二叉树的方法不同,作者预先构建了一棵包含所有积分范围的树,树的每一层会根据范围划分,再将每一个需要统计排名的积分通过范围的比较放入树中,更新树的时候会更新每一层所包含的积分数量。当需要获取积分排名的时候,只需要获取每一层大于该积分的积分数量相加即可,时间复杂度可达到O(logn)。具体的实现方法建议直接进入文章查看。
使用现有工具的方法
1.使用SQL查询。
当数据量不大的时候可以直接使用数据库的查询。使用INSERT,UPDATE插入与更新玩家,使用SELECT COUNT查询分数高于某个玩家的人数,即是该玩家的排名。
好处是数据操作的细节被数据库隐藏了,在数量较少的时候能够提供方便的操作,缺点是当数据量大的时候,相较于操作放置于内存的数据结构,其性能会非常低下。
2.使用Redis的sorted set
其内部使用了Hash table和skip list,用来做排行榜有着天生的优势:提供了丰富的排行榜查询接口,例如zrank()用于查询指定元素的排名(下标),zrevrange()用于获取指定区间的元素。
3.使用Erlang有序异键形式(sorted set)的ETS
也有许多团队选择使用Erlang语言进行游戏开发,此时Erlang自带的ETS也是不错的选择。ETS的有序异键表是用平衡二叉树实现的。
一些需要考量的其他因素
排行榜可以定时更新,还是需要同步更新?
排行榜是严格排行榜是可以存在并列排名的排行榜?
如果是同步更新的严格排行榜,则需要自己制定在分数相同情况下的排行规则,一些 有着默认排行规则的排行榜用不了。
除此之外,需要进行排行的玩家数量也是很关键的因素,如果玩家数量不多,或者对于排行过低的玩家排名的准确性(甚至是是否展示排名)不做太强制的要求,除却上面的方法可能还有更适合的实现方式。
备忘参考:
海量用户积分排名算法探讨
https://www.cnblogs.com/weidagang2046/archive/2012/03/01/massive-user-ranking.html
游戏排行榜 – 基于skiplist计算rank排名
https://yuerblog.cc/2019/02/13/skiplist-rank/
在C#中使用二叉树实时计算海量用户积分排名的实现
https://cloud.tencent.com/developer/article/1621522
简单高效的排行榜算法——树状数组
https://www.owenzhang.net/blog/325.html
谈谈陌陌争霸在数据库方面踩过的坑(排行榜篇)
https://blog.codingnow.com/2014/03/mmzb_db_2.html
排行榜算法设计实现比较
https://gameinstitute.qq.com/community/detail/101951
使用Redis Zset来处理活动常用排行榜(精确排行)
https://segmentfault.com/a/1190000011737336
如何对游戏服务器全服玩家进行排名?
https://www.zhihu.com/question/27933771
海量用户的积分排序问题算法的分析
https://segmentfault.com/a/1190000004268386
开发笔记:基于积分的游戏排行榜实现方式探讨相关推荐
- 【Visual C++】游戏开发笔记二十二 游戏基础物理建模(四) 粒子系统模拟(一)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7585937 作者:毛星云 邮箱: h ...
- 【Visual C++】游戏开发笔记二十二 游戏基础物理建模 四 粒子系统模拟 一
分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...
- 【Visual C++】游戏开发笔记二十二 游戏基础物理建模(四) 粒子系统模拟(一) .
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7585937 作者:毛星云 邮箱: h ...
- Egret实战开发笔记,飞行射击游戏(六)
今天是开发飞行射击游戏第五天,玩家多类型子弹及状态和关卡模式. 简介 实现玩家特殊子弹,激光,追踪导弹. 玩家多状态 下方飞出 正常游戏 胜利等待 胜利飞出 以及 玩家保护 和 关卡切换 实现效果 本 ...
- Egret实战开发笔记,飞行射击游戏(二)
简介 Egret实战开发,记录每天的学习进度,欢迎和我一起学习交流~ 目录 简介 实现目标 一.实现子弹类 二.工厂设计模式 三.子弹管理类ZDManager 实现目标 今天是开发飞行射击游戏第二天, ...
- 大学android移动开发笔记,基于Android的移动模拟练习系统的设计与实现
李思莉 聂芝献 摘要:该文主要论述基于Android的移动模拟练习系统的功能设计及数据设计.数据实现.该系统客户端使用基于Android的移动应用开发技术,服务器端采用JAVA WEB+MySQL技术 ...
- iOS开发笔记--基于面向协议MVP模式下的软件设计
传统模式下的开发 MVC MVVM 基于面向协议MVP的介绍 MVP实战开发 说在前面: 相信就算你是个iOS新手也应该听说过MVC的,MVC是构建iOS App的标准模板.随着时间的推移,在iOS ...
- 【游戏开发】基于MMORPG的游戏客户端逻辑效率开发思路
思考:如何提升游戏逻辑开发效率 提升游戏逻辑开发效率的关键在于:游戏新增或修改功能时,需要尽可能减少程序需要重复开发的代码量. 下面主要考虑以下三种减少编码工作量的方法: <1>.尽可能将 ...
- IOS开发笔记 - 基于SDWebImage的网络图片加载处理
前言: 在IOS下通过URL读一张网络图片并不像Asp.net那样可以直接把图片路径放到图片路径的位置就ok, 而是需要我们通过一段类似流的方式去加载网络图片,接着才能把图片放入图片路径显示. 这里找 ...
最新文章
- python是基于什么语言开发-2.python是什么编程语言。
- laravel中及其常用的一些函数方法(自己看)和技巧(不断添加中)
- (error) LOADING Redis is loading the dataset in memory问题解决
- matpython_[mcj]使用Matlab/Python合并mat文件并存为mat
- 中南民族大学c语言报告,中南民族大学信C语言实验报告.doc
- 基于PaddleRec的用户点击率预测
- linux ifconfig
- windows中端口号被占用的解决方法
- 技术实践丨体验量子神经网络在自然语言处理中的应用
- Activity生命周期Android,横屏切换不重新创建Activity, Activity的四种launchMode
- AcWing 852. spfa判断负环(spfa or bellman)
- 拓端tecdat|R语言自适应平滑样条回归分析
- 基于PHP的校园bbs论坛系统
- hackerrank Java Data Structures
- 伍斯特理工学院计算机科学硕士,美国伍斯特理工学院计算机科学硕士入学要求.pdf...
- ios 开发控件中心点_AppCan
- visio2019和Mathtype7.0版本冲突,出现VBE6EXT.OLB不能被加载
- 数据分析大数据面试题大杂烩01
- 最新校招笔试面试六十题
- 希捷160G 7200.10 8Mb硬盘辨真伪!