游戏排行榜的一种实现
我是游戏公司小猿一只,做游戏服务器开发。最近公司准备招新的 C++ 程序员,我一般都会问到一个常见的功能,一万人排行榜怎么实现。
得到的答案很多,比如 “1.直接从数据库中读取;2.用 hash 表;3.用一个环形数组;4.这个问题我要仔细考虑一下。”
对于这些答案我是不满意的,因为从事游戏逻辑开发的人,排行榜功能是一个基础功能,出于“优秀”C++ 程序员的本能,应该细想怎样实现之。对这个功能如果仅仅停留在表面,心理大概推测用什么数据结构,在关键性问题上支支吾吾,我可能不大愿意和这样的同事共事。我并非是一帮子打死所有不能在十分钟内给出好答案的人,而是想得到一个“正确的本能反应”,考虑的方向上是正确的即可。
给出一个我认为可行而且性能较好的实现方法。
排行榜这种功能,基础容器肯定是数组,vector 。因为排行榜要支持一个特性就是“根据名次找到人”。其他的容器并不支持这样的特性。
vector 中保存的是 Player 指针,和排行用到的 key,(比如等级排行榜的 key 是“等级”“0xffffffff - 时间戳“的组合)。
Player 结构中保存有排行榜名次。
排行榜 玩家数据
第一名 key1, Player * p1 p1 {myrank : 1, ...}
第二名 key2, Player * p2 p2 {myrank : 2, ...}
第三名 key3, Player * p3 p3 {myrank : 3, ...}
第四名 key4, Player * p4 p4 {myrank : 4, ...}
服务器启动时,将前一万名整理好,无论用快速排序、堆排序、插入排序、还是冒泡排序都无所谓。
游戏中,玩家数据有变化需要更新排行榜时,根据 myrank 找到玩家对应的榜位置,依次向上做冒泡比较,移动该玩家数据的同时,更新被移动的玩家 myrank 即可。这样就得到了一个新的排行榜。
极端情况不大可能存在,最后一名的玩家不可能跳跃性跳到第一名,而是渐渐的向上挪动,所以采用冒泡的方式并不会影响性能。