需求

在网络游戏中,服务器通常会对全服玩家的某些数据进行排名,如等级、战力、活动获取的积分等等。而对于排行榜,需做到以下要求求:

  • 排行榜需要做到实时,如玩家战力提升,立马看到新的排名
  • 只关心前N名玩家的排名,通常 N <= 1000
  • 排名分前后顺序,不可并列,如同一战力,先达到的排名靠前

实现

源码地址

https://github.com/zifengzwz/sundrycpp/tree/main/rank

目录结构

.
├── CMakeLists.txt
├── main.cpp
└── sorted_set.hpp

sorted_set.hpp

#ifndef SORTED_SET
#define SORTED_SET#include <memory>
#include <set>
#include <unordered_map>template <class Key, class T>
class sorted_set {public:using key_type = Key;using value_type = T;using size_type = std::size_t;// default: care of top 1000static constexpr size_type default_top = 1000;struct key_value_type {key_type first;value_type second;key_value_type(const key_type& k, const value_type& v): first(k), second(v) {}};using key_value_ptr = std::shared_ptr<key_value_type>;struct key_value_less {constexpr bool operator()(const key_value_ptr& left,const key_value_ptr& right) const {if (left->second == right->second) {return left->first < right->first;}return left->second < right->second;}};sorted_set() : top_(default_top) {}explicit sorted_set(size_type top) : top_(top == 0 ? default_top : top) {}sorted_set(const sorted_set&) = delete;sorted_set& operator=(const sorted_set&) = delete;~sorted_set() = default;sorted_set(sorted_set&& right): top_(right.top_),map_(std::move(right.map_)),set_(std::move(right.set_)) {}sorted_set& operator=(sorted_set&& right) noexcept {top_ = right.top_;map_ = std::move(right.map_);set_ = std::move(right.set_);return *this;}// ranged-for: large->smallauto begin() const { return set_.rbegin(); }auto end() const { return set_.rend(); }auto find(key_type k) { return map_.find(k); }auto map_end() { return map_.end(); }auto set_end() { return set_.end(); }void insert(const key_type& k, const value_type& v) {auto add = [&] {key_value_ptr ptr = std::make_shared<key_value_type>(k, v);map_.emplace(k, ptr);set_.insert(ptr);};auto it = map_.find(k);if (it == map_.end()) {if (set_.size() < top_) {add();} else if (set_.size() == top_) {auto val = v;if (val < (*set_.begin())->second) return;map_.erase((*set_.begin())->first);set_.erase(set_.begin());add();}} else {set_.erase(it->second);map_.erase(it);add();}}void erase(const key_type& k) {auto it = map_.find(k);if (it == map_.end()) return;set_.erase(it->second);map_.erase(it);}void clear() {set_.clear();map_.clear();}size_type size() { return set_.size(); }size_type rank(const key_type& k) {auto it = map_.find(k);if (it == map_.end() || set_.empty()) return 0;size_type rank = 0;for (auto n = set_.rbegin(); n != set_.rend(); ++n) {++rank;if ((*n)->first == k) return rank;}return 0;}private:size_type top_;std::unordered_map<key_type, key_value_ptr> map_;std::set<key_value_ptr, key_value_less> set_;
};#endif
  • 这里使用标准库的setunordered_map简单地实现sorted_set(有序集合)
  • 参与排名的userid与排名数据为一个整体,作为set的元素和unordered_map的值,userid为unordered_map的键
  • 利用set的红黑树结构进行自排序,unordered_map哈希特性进行快速索引
  • 默认排名为前1000(default_top)
  • 通常排名在单线程中进行,无需考虑多线程安全,禁用拷贝构造和赋值操作
  • 添加了beginend方法,支持从大到小的范围for循环

main.cpp

#include <chrono>
#include <cstdint>
#include <iostream>
#include <random>#include "sorted_set.hpp"struct rank_item {int score{0};int64_t time{0};bool operator<(const rank_item& r) {if (score == r.score) {return time > r.time;}return score < r.score;}bool operator==(const rank_item& r) {return score == r.score && time == r.time;}
};// [left, right]
int rand_num(int left, int right) {static std::default_random_engine gen(std::random_device{}());std::uniform_int_distribution<decltype(right)> dis(left, right);return dis(gen);
}int64_t get_time_milli() {auto now = std::chrono::system_clock::now().time_since_epoch();return std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
}int main(int argc, char* argv[]) {sorted_set<int, rank_item> rank_info;for (int i = 1; i <= 10; ++i) {rank_info.insert(i, rank_item{rand_num(50, 100), get_time_milli()});}int rank = 1;for (auto& n : rank_info) {std::cout << "rank: " << rank << ", userid: " << n->first<< ", score: " << n->second.score << std::endl;++rank;}return 0;
}
  • 对于排名数据rank_item,需重载<和==运算符
  • 随机生成50-100之间的数值作为得分,对userid为1-10的玩家进行排名

CMakeLists.txt

cmake_minimum_required(VERSION 3.19)
project(rank LANGUAGES CXX)
SET(CMAKE_CXX_STANDARD 17)
add_executable(rank main.cpp sorted_set.hpp)
  • 由于使用了一些新特性,需要cmake添加对C++17标准的支持

编译运行

# mkdir build
# cd build
# cmake ..
# cmake --build .
# ./rank
rank: 1, userid: 4, score: 100
rank: 2, userid: 8, score: 97
rank: 3, userid: 5, score: 94
rank: 4, userid: 9, score: 91
rank: 5, userid: 2, score: 89
rank: 6, userid: 3, score: 75
rank: 7, userid: 6, score: 70
rank: 8, userid: 7, score: 68
rank: 9, userid: 10, score: 64
rank: 10, userid: 1, score: 55

游戏实时排行榜C++实现相关推荐

  1. 用 Redis 搞定游戏中的实时排行榜,附源码!

    原文:segmentfault.com/a/1190000019139010 1. 前言 前段时间刚为项目(手游)实现了一个实时排行榜功能, 主要特性: 实时全服排名 可查询单个玩家排名 支持双维排序 ...

  2. [原创]游戏中的实时排行榜实现

    1. 前言 2. 排行榜分类 3. 思路 4. 实现 复合排序 4.1 等级排行榜 4.2 通天塔排行榜 4.3 坦克排行榜 5. 排名数据的动态更新 6. 取排行榜 7. Show The Code ...

  3. 游戏服务器排行榜的设计

    排行榜是游戏服务器中不可缺少的一部分,几乎所有的游戏都有排行榜.游戏排行榜根据排行榜需要上榜的人数有不同的设计,但是普遍来说一般都是显示前100名或者50名,排行榜排100,1k,1w人数,超过1w名 ...

  4. 移动互联网实战--社交游戏的排行榜设计和实现(2)

    前言: 游戏领域, 特别是移动端的社交类游戏, 排行榜成为了一种增强体验交互, 提高用户粘性的大法宝. 这边讲述在不同用户规模下, 游戏服务化/游戏平台化趋势下, 如何去设计和实现游戏排名榜. 本文侧 ...

  5. 社交游戏的排行榜设计和实现:mysql数据库的应用

    前言 游戏领域, 特别是移动端的社交类游戏, 排行榜成为了一种增强体验交互, 提高用户粘性的大法宝. 这边讲述在不同用户规模下, 游戏服务化/游戏平台化趋势下, 如何去设计和实现游戏排名榜. 本文侧重 ...

  6. 游戏服排行榜实现(面试被问到)

    最近面试连续被问到游戏服排行榜如何实现,因为以前一直不觉得是个事,所以突然问到一脸懵逼,现在我自己总结一下. 目前工作中KE排行榜的实现 1.单服排行榜,直接用ruby on rails封装的查询语句 ...

  7. 2020年CSDN博客之星实时排行榜——热门有你

    我根据C#抓取了博客之星页面的数据,做一个实时排行榜,数据截止 2021年01月23日 10:20 拉票太难了!大家有余票的,支持下我啊!编号150号: 支持点我投票. 排名 博主 票数 投票 1 博 ...

  8. 能玩java游戏oppo按键手机_游戏手机排行榜|OPPO Reno果然不负期待

    王者荣耀.绝地求生.阴阳师等游戏,都是如今非常受小年轻欢迎的手游,考虑到消费者体验,各大手机厂商在设计手机时,往往会把游戏体验考虑进去.下面,我们整理了一份目前较受欢迎的游戏手机排行榜,大家在购机时可 ...

  9. apache在线升级yum_基于Redis实现在线游戏积分排行榜 - phyger

    介绍 本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能. 背景知识 Redis Redis是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化 ...

最新文章

  1. UI事件与内容,舞台与演员
  2. 深入理解JVM(1)——Java内存区域与Java对象
  3. 锐捷云课堂助力海南农垦中学 根治计算机教室“老病根”
  4. 【52】写了placement new也要写placement delete
  5. 李飞飞斯坦福博士提出SLIDE模型
  6. Http请求中Content-Type
  7. QT pro文件 Win/Linux跨平台写法
  8. 电脑怎么让图片颜色反转?怎么调图片反色效果?
  9. 微软代码审查工具_Microsoft如何进行代码审查?
  10. html5 播放器 github,GitHub - Little-girl-lily/player: html5版本音乐播放器,支持iOS设备...
  11. 学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计 汉语言文学设计题材网页
  12. 基于Linux Rational Performance Tester自动化测试研究
  13. 魔兽怀旧玩家显示服务器名称插件,新手必看:非插件相关的魔兽怀旧服常用系统设置...
  14. 团队里不能留的三种人
  15. 华清见远 pcie网卡驱动_使用PCIe交换网结构在多主机系统中优化资源部署
  16. labview在不同VI间传递波形(全局变量)
  17. 不仅是工程学!人类认知偏差导致的12个AI研究盲区
  18. _Win7_Ultimate_x64_.gho
  19. HCIA网络基础11-IP路由原理及静态路由
  20. 服务器系统用热备盘嘛,服务器设置热备盘

热门文章

  1. PDF在线预览(java实现)
  2. 你知道互联网行业哪些岗位需求量最大?什么职位最赚钱?
  3. Mr. X and His Shots
  4. 快速入门!Python爬虫,京东自动登录,在线抢购商品!
  5. Ubuntu18.04.5 LTS 安装优麒麟应用商店的坑
  6. 如何开展应届生面试工作
  7. 整型数组处理算法(十二)请实现一个函数:最长顺子。[风林火山]
  8. 8.2 自定义 Git - Git 属性
  9. 6、远程终端工具安装
  10. 音乐是我们日常生活中不可缺少的