标签:private ret for 简单 多少 一个 规模 弊端 var
排行榜是游戏中一个常见的系统,不过要做好并不容易,比如要对全服几W名玩家做实时排行的话,性能需要花心思去优化的问题。
这里设计了一个基于桶排序的面向全服玩家的通用排行榜
一个简单的思路就是按排序的KEY的分值进行分桶,但是一个弊端就是随着游戏生命推进,会出现一个分数段类的玩家大规模集中,导致分桶失去意义。
所以这里采用了对桶的容量做上限,然后达到上限就分裂桶然后动态计算桶的上下限的做法
桶的定义如下(代码采用c#编写):
class sub_rank_list { public Hashtable low; public Hashtable up; private HashSet<String> mem_set; public List<Hashtable> rank_list; private IComparer<Hashtable> comparer; }
使用Hashtable描述排序的信息是为了排行榜的通用性。
每个Hashtable中需要包含对应玩家的unionid和排序信息
玩家的unionid保存在mem_set中(在mem_set中可以找到玩家的id,表示玩家在这个桶内)
要获取一个玩家在排行榜上的排名,则先查找到玩家在哪个桶内,然后计算 这个桶前有多少玩家和玩家在该桶内的排名之和就是玩家的排名
public int get_rank(String uuid) { int rank = 0; foreach(var sub_rank_list in rank_data) { if (!sub_rank_list.in_rank(uuid)) { rank += sub_rank_list.count(); continue; } rank += sub_rank_list.rank(uuid); break; } return rank; }
整个排行榜的代码如下:
using System; using System.Collections; using System.Collections.Generic; namespace rank { //升序排行 class rank { public rank(IComparer<Hashtable> _comparer) { rank_data = new List<sub_rank_list>(); comparer = _comparer; } public void clear_rank() { rank_data = new List<sub_rank_list>(); } public void update_rank(Hashtable data) { String uuid = (String)data["uuid"]; foreach(var sub_list in rank_data) { if (!sub_list.in_rank(uuid)) { continue; } if (sub_list.in_range(data)) { sub_list.update_rank(data); } else { sub_list.del_rank(uuid); insert_rank(data); } break; } } public void insert_rank(Hashtable data) { sub_rank_list sub_list = null; sub_rank_list up_list = null; sub_rank_list low_list = null; foreach (var _sub_list in rank_data) { if (up_list == null) { up_list = _sub_list; } else { if (comparer.Compare(up_list.up, _sub_list.up) < 0) { up_list = _sub_list; } } if (low_list == null) { low_list = _sub_list; } else { if (comparer.Compare(low_list.low, _sub_list.low) > 0) { low_list = _sub_list; } } if (!_sub_list.in_range(data)) { continue; } sub_list = _sub_list; break; } if (sub_list == null) { if (low_list == null && up_list == null) { sub_list = new sub_rank_list(data, data, comparer); } else { if (comparer.Compare(low_list.low, data) > 0) { sub_list = low_list; sub_list.low = data; } if (comparer.Compare(up_list.up, data) < 0) { sub_list = up_list; sub_list.up = data; } } } sub_list.insert_rank(data); if (sub_list.count() > 2000) { var new_rank = sub_list.split_rank(); rank_data.Add(new_rank); for(int i = 0; i < rank_data.Count - 1; i++) { var rank1 = rank_data[i]; var rank2 = rank_data[i + 1]; if (comparer.Compare(rank1.low, rank2.up) < 0) { rank_data[i] = rank2; rank_data[i + 1] = rank1; } } } } public int get_rank(String uuid) { int rank = 0; foreach(var sub_rank_list in rank_data) { if (!sub_rank_list.in_rank(uuid)) { rank += sub_rank_list.count(); continue; } rank += sub_rank_list.rank(uuid); break; } return rank; } public Hashtable get_rank(int rank) { int rank_low = 0; int rank_up = 1; foreach(var sub_rank_list in rank_data) { rank_low = rank_up; rank_up += sub_rank_list.count(); if (rank >= rank_low && rank < rank_up) { return sub_rank_list.rank_list[rank - rank_low]; } } return null; } class sub_rank_list { public sub_rank_list(Hashtable _low, Hashtable _up, IComparer<Hashtable> _comparer) { low = _low; up = _up; mem_set = new HashSet<String>(); rank_list = new List<Hashtable>(); comparer = _comparer; } public bool in_range(Hashtable data) { int c1 = comparer.Compare(data, up); int c2 = comparer.Compare(data, low); return c1 <= 0 && c2 > 0; } public bool in_rank(String uuid) { return mem_set.Contains(uuid); } public int count() { return mem_set.Count; } public int rank(String uuid) { int rank = 0; foreach(var mem in rank_list) { rank++; if (uuid == (String)mem["uuid"]) { break; } } return rank; } public void update_rank(Hashtable data) { foreach(var _data in rank_list) { if ((String)_data["uuid"] != (String)data["uuid"]) { continue; } rank_list.Remove(_data); break; } rank_list.Add(data); rank_list.Sort(comparer); } public void del_rank(String uuid) { foreach (var _data in rank_list) { if ((String)_data["uuid"] != uuid) { continue; } mem_set.Remove(uuid); rank_list.Remove(_data); break; } } public void insert_rank(Hashtable data) { mem_set.Add((String)data["uuid"]); rank_list.Add(data); rank_list.Sort(comparer); } public sub_rank_list split_rank() { sub_rank_list new_rank = new sub_rank_list(low, up, comparer); int _count = count() / 2; Hashtable data = null; for (int i = 0; i < _count; i++) { data = rank_list[i]; del_rank((String)data["uuid"]); new_rank.insert_rank(data); } new_rank.low = data; up = rank_list[0]; return new_rank; } public Hashtable low; public Hashtable up; private HashSet<String> mem_set; public List<Hashtable> rank_list; private IComparer<Hashtable> comparer; } private List<sub_rank_list> rank_data; private IComparer<Hashtable> comparer; } }
标签:private ret for 简单 多少 一个 规模 弊端 var
原文地址:http://www.cnblogs.com/qianqians/p/7288474.html