通用排行榜组件
简介:
排行榜是游戏组件中必不可少的组件,设计一个可重用的排行榜是必不可少的,一个排行榜系统需要满足如下要求:
排行榜一般是限制名次的,比如只为前100 名进行排名 排行榜一般会有多种,比如等级排行榜、金币排行榜等 有时排行榜需要定时更新,有时需要实时更新排行系统组件关系图:
创建排行榜
rank_obj_mgr_t rank_obj_mgr;
rank_system_t rank_system( & rank_obj_mgr);
enum
{
LEVEL_RANK = 1
};
// ! 等级排行榜, 排名前一百个
rank_system.create_ranklist(LEVEL_RANK, 100 );
典型的对象管理器的实现:
class rank_obj_mgr_t
{
public :
virtual int add( long id, rank_obj_t* obj_)
{
return m_objs.insert(make_pair(id, obj_)).second == true ? 0 : - 1 ;
}
virtual void del( long id_)
{
m_objs.erase(id_);
}
virtual rank_obj_t* find( long id_)
{
map < long , rank_obj_t*>::iterator it = m_objs.find(id_);
return it != m_objs.end()? it-> second: NULL;
}
template <typename T>
void foreach (T func_)
{
for (map< long , rank_obj_t*>::iterator it = m_objs.begin(); it != m_objs.end(); ++ it)
{
func_(it -> second);
}
}
private :
map < long , rank_obj_t*> m_objs;
};
实体对象必须具有多个属性值:
class rank_obj_t
{
public :
rank_obj_t():m_rank( 0 ){}
virtual ~ rank_obj_t() {}
virtual long get_attr( int AttrId)
{
if (AttrId == LEVEL_RANK) return 100 ; // ! 示例代码而已
return - 1 ;
}
void set_rank( int rank_) { m_rank = rank_; }
int get_rank() const { return m_rank; }
private :
int m_rank;
};
定时排行的实现:
实际上是利用了multimap的有序性完成的
void ranklist_t::sort()
{
m_ranklist_sort_map.clear();
m_ranklist_cache_vt.clear();
sort_functor_t func(m_attr_id, & m_ranklist_sort_map, m_max_rank_num);
m_rank_obj_mgr -> foreach (func);
resort_ranklist( 1 , m_ranklist_sort_map.begin(), m_ranklist_sort_map.end());
}
实时排名的实现:
ranklist_t::sort_map_t::iterator ranklist_t::find( long attr_, rank_obj_t* obj_)
{
pair <sort_map_t::iterator, sort_map_t::iterator> ret = m_ranklist_sort_map.equal_range(attr_);
for (sort_map_t::iterator it=ret.first; it != ret.second; ++ it)
{
if (it->second == obj_)
{
return it;
}
}
return m_ranklist_sort_map.end();
}
int ranklist_t::update_obj(rank_obj_t* obj_)
{
long now_attr = obj_-> get_attr(m_attr_id);
int old_rank = obj_-> get_rank();
if ( 0 == old_rank) // ! 还未加入排行榜
{
sort_map_t::iterator it_new = m_ranklist_sort_map.insert(make_pair(now_attr, obj_));
int now_rank = 1 ;
if (it_new != m_ranklist_sort_map.begin())
{
sort_map_t::iterator ItTmp = it_new;
sort_map_t::iterator ItBefore = -- ItTmp;
now_rank = ItBefore->second->get_rank() + 1 ;
}
resort_ranklist(now_rank, it_new, m_ranklist_sort_map.end());
check_rank_num_limit();
return - 1 ;
}
// ! 已经加入过排行榜, 检查排名是否发生变化
// ! 如果排名没有发生变化,直接返回
// ! 需要知道变化的开始、介绍的iterator, 以及从第几个排名开始变化
long old_attr = m_ranklist_cache_vt[old_rank].old_attr;
sort_map_t::iterator begin_change_it, end_change_it;
int begin_change_rank = 1 ;
if (now_attr >old_attr) // ! 排名可能向前涨
{
if (is_first(old_rank) || now_attr <= m_ranklist_cache_vt[old_rank - 1 ].old_attr)
{
// ! 排名不变
return 0 ;
}
if (is_last(old_rank)) // ! 最后一名
{
sort_map_t::iterator tmp_it = find(old_attr, obj_);
m_ranklist_sort_map.erase(tmp_it);
begin_change_it = m_ranklist_sort_map.insert(make_pair(now_attr, obj_));
end_change_it = m_ranklist_sort_map.end();
}
else
{
rank_obj_t * next_obj = m_ranklist_cache_vt[old_rank + 1 ].rank_obj;
sort_map_t::iterator tmp_it = find(old_attr, obj_);
m_ranklist_sort_map.erase(tmp_it);
begin_change_it = m_ranklist_sort_map.insert(make_pair(now_attr, obj_));
end_change_it = find(next_obj-> get_attr(m_attr_id), next_obj);
}
// ! 计算从第几个排名后开始发生变化
if (begin_change_it == m_ranklist_sort_map.begin())
{
begin_change_rank = 1 ;
}
else
{
sort_map_t::iterator pre_it = begin_change_it;
begin_change_rank = (++pre_it)->second->get_rank() + 1 ;
}
}
else // ! 排名可能向后退
{
if (is_last(old_rank) || now_attr >= m_ranklist_cache_vt[old_rank + 1 ].old_attr)
{
// ! 排名不变
return 0 ;
}
if (is_first(old_rank)) // ! 最后一名
{
sort_map_t::iterator tmp_it = find(old_attr, obj_);
m_ranklist_sort_map.erase(tmp_it);
end_change_it = m_ranklist_sort_map.insert(make_pair(now_attr, obj_));
++ end_change_it;
begin_change_it = m_ranklist_sort_map.begin();
begin_change_rank = 1 ;
}
else
{
rank_obj_t * pre_obj = m_ranklist_cache_vt[old_rank - 1 ].rank_obj;
sort_map_t::iterator tmp_it = find(old_attr, obj_);
m_ranklist_sort_map.erase(tmp_it);
end_change_it = m_ranklist_sort_map.insert(make_pair(now_attr, obj_));
++ end_change_it;
begin_change_it = find(pre_obj-> get_attr(m_attr_id), pre_obj);
}
// ! 计算从第几个排名后开始发生变化
begin_change_rank = old_rank;
}
resort_ranklist(begin_change_rank, begin_change_it, end_change_it);
return - 1 ;
}
int ranklist_t::get_rank( int from_, int to_, vector<rank_obj_t*>& ret_)
{
int begin = (from_ > 0 && (size_t)from_ < m_ranklist_cache_vt.size())? from_: 0 ;
int end = (to_ > 0 && (size_t)to_ < m_ranklist_cache_vt.size())? to_: 0 ;
end = end > begin? end: begin;
for ( int i = begin - 1 ; i < end; ++ i)
{
ret_.push_back(m_ranklist_cache_vt[i].rank_obj);
}
return 0 ;
}
void ranklist_t::resort_ranklist( int rank_, sort_map_t::iterator it_begin_, sort_map_t::iterator it_end_)
{
rank_info_t tmp_info;
for (sort_map_t::iterator it = it_begin_; it != it_end_; ++ it)
{
tmp_info.rank = rank_++ ;
tmp_info.rank_obj = it-> second;
tmp_info.old_attr = tmp_info.rank_obj-> get_attr(m_attr_id);
tmp_info.rank_obj -> set_rank(tmp_info.rank);
if (tmp_info.rank >= ( int )m_ranklist_cache_vt.size())
{
m_ranklist_cache_vt.push_back(tmp_info);
}
else
{
m_ranklist_cache_vt[tmp_info.rank - 1 ] = tmp_info;
}
}
}
int ranklist_t::check_rank_num_limit()
{
if (m_ranklist_cache_vt.size() <= (size_t)m_max_rank_num)
{
return 0 ;
}
m_ranklist_sort_map.erase( -- (m_ranklist_sort_map.end()));
m_ranklist_cache_vt.erase(m_ranklist_cache_vt.begin() + (m_ranklist_cache_vt.size() - 1 ));
return - 1 ;
}
标签: cpp , ranklist
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did48071