代码改变世界

游戏排行榜的一种实现

2015-04-17 10:01  刘腾达的博客  阅读(2112)  评论(0编辑  收藏  举报

游戏排行榜的一种实现

我是游戏公司小猿一只,做游戏服务器开发。最近公司准备招新的 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 即可。这样就得到了一个新的排行榜。

极端情况不大可能存在,最后一名的玩家不可能跳跃性跳到第一名,而是渐渐的向上挪动,所以采用冒泡的方式并不会影响性能。