好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

通用排行榜组件

通用排行榜组件

简介:

排行榜是游戏组件中必不可少的组件,设计一个可重用的排行榜是必不可少的,一个排行榜系统需要满足如下要求:

排行榜一般是限制名次的,比如只为前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://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于通用排行榜组件的详细内容...

  阅读:44次

上一篇: gcc编译系统

下一篇:各大类库的类工厂