做网站域名,南昌做公司网站,网站新备案不能访问,保护动物网站建设策划书玩家匹配是根据自己的天梯分数进行匹配的#xff0c;而服务器中将玩家天梯分数分为三个档次#xff1a; 1. 普通#xff1a;天梯分数小于2000分 2. 高手#xff1a;天梯分数介于2000~3000分之间 3. 大神#xff1a;天梯分数大于3000分 当玩家进行对战匹配时#xff0c;服…玩家匹配是根据自己的天梯分数进行匹配的而服务器中将玩家天梯分数分为三个档次 1. 普通天梯分数小于2000分 2. 高手天梯分数介于2000~3000分之间 3. 大神天梯分数大于3000分 当玩家进行对战匹配时服务器会根据档次将玩家送到不同档次的匹配队列当中。共有3个匹配队列分别是普通队列、高手队列和大神队列每一条队列由单独的线程去控制。因此匹配对战模块需要由两个类一个类是匹配队列的类另外一个是管理匹配队列的类。
匹配队列类
当玩家进行匹配对战的请求后服务器会将玩家添加至相应的匹配队列当中匹配成功后会从匹配队列中移除该玩家而在匹配成功前玩家可能会中止匹配。因此匹配队列应该包含的功能有入队、出队、和移除指定玩家玩家处在的位置可能是队列的中间因此匹配队列采用的是双向循环链表。在匹配过程中如果暂时为达到匹配玩家个数该线程会进入阻塞等待状态因此需要实现的功能还有阻塞等待的方法获取队列元素个数、判断队列是否为空的方法。
templateclass T
class match_queue
{
private:/*由于可能要删除中间数据因此使用双向链表而不使用队列*/std::listT _list;//保证线程安全std::mutex _mutex;//使用条件变量实现阻塞在队列中元素个数小于2的时候进行阻塞std::condition_variable _cond;
public:/*入队*/void push(T data){std::unique_lockstd::mutex lock(_mutex);_list.push_back(data);/*每次有玩家进入匹配队列后唤醒线程*/_cond.notify_all();}/*出队*/bool pop(T data){std::unique_lockstd::mutex lock(_mutex);if(_list.empty()true){return false;}data _list.front();_list.pop_front();return true;}/*移除指定元素*/void remove(T data){std::unique_lockstd::mutex lock(_mutex);_list.remove(data);}/*获取队列元素个数*/int size(){std::unique_lockstd::mutex lock(_mutex);return _list.size();}/*判断队列是否为空*/bool empty(){std::unique_lockstd::mutex lock(_mutex);return _list.empty();}/*阻塞等待*/void wait(){std::unique_lockstd::mutex lock(_mutex);_cond.wait(lock);}};
匹配队列管理类
在匹配队列管理类中创建三个线程每一个线程分别管理着每一条匹配队列
普通线程管理普通队列高手线程管理高手队列大神线程管理大神队列。
而管理的方法是实现匹配对战当玩家数量小于2时线程继续阻塞。大于2时将两个玩家出队然后将玩家添加到房间最后对玩家进行一个匹配成功的响应。
#ifndef __M__MATCHER_H__
#define __M__MATCHER_H__
#includelist
#include mutex
#include condition_variable
#include room.hpptemplateclass T
class match_queue
{
private:/*由于可能要删除中间数据因此使用双向链表而不使用队列*/std::listT _list;//保证线程安全std::mutex _mutex;//使用条件变量实现阻塞在队列中元素个数小于2的时候进行阻塞std::condition_variable _cond;
public:/*入队*/void push(T data){std::unique_lockstd::mutex lock(_mutex);_list.push_back(data);/*每次有玩家进入匹配队列后唤醒线程*/_cond.notify_all();}/*出队*/bool pop(T data){std::unique_lockstd::mutex lock(_mutex);if(_list.empty()true){return false;}data _list.front();_list.pop_front();return true;}/*移除指定元素*/void remove(T data){std::unique_lockstd::mutex lock(_mutex);_list.remove(data);}/*获取队列元素个数*/int size(){std::unique_lockstd::mutex lock(_mutex);return _list.size();}/*判断队列是否为空*/bool empty(){std::unique_lockstd::mutex lock(_mutex);return _list.empty();}/*阻塞等待*/void wait(){std::unique_lockstd::mutex lock(_mutex);_cond.wait(lock);}
};class matcher
{
private:/*普通队列*/match_queueuint64_t _q_normal;/*高手队列*/match_queueuint64_t _q_hight;/*大神队列*/match_queueuint64_t _q_super;/*普通线程*/std::thread _th_normal;/*高手线程*/std::thread _th_hight;/*大神线程*/std::thread _th_super;room_manager *_rm;user_table *_ut;online_manager *_om;
private:void handle_match(match_queueuint64_t mq){while(1){/*判断队列中玩家个数是否大于2*/while(mq.size()2){mq.wait();}/*大于2将两个玩家出队*/uint64_t uid1,uid2;bool ret mq.pop(uid1);if(retfalse){continue;}ret mq.pop(uid2);if(retfalse){continue;}/*两个玩家出队后获取对应的通信连接,然后判断是否依然连接在线*/wsserver_t::connection_ptr conn1 _om-get_conn_from_hall(uid1);if(conn1.get()nullptr){this-add(uid1);continue;}wsserver_t::connection_ptr conn2 _om-get_conn_from_hall(uid2);if(conn2.get()nullptr){this-add(uid2);continue;}/*获取连接后为他们创建房间并且添加进房间*/room_ptr rp _rm-create_room(uid1,uid2);if(rp.get()nullptr){this-add(uid1);this-add(uid2);continue;}/*将信息返回*/Json::Value resp;resp[optype] match_success;resp[result] true;std::string body;json_util::serialize(resp,body);conn1-send(body);conn2-send(body);}}void _th_normal_entry(){return handle_match(_q_normal);}void _th_hight_entry(){return handle_match(_q_hight);}void _th_super_entry(){return handle_match(_q_super);}
public:matcher(room_manager *rm,user_table* ut,online_manager* om):_rm(rm),_ut(ut),_om(om),_th_normal(std::thread(matcher::_th_normal_entry,this)),_th_hight(std::thread(matcher::_th_hight_entry,this)),_th_super(std::thread(matcher::_th_super_entry,this)){DLOG(游戏匹配模块初始化完毕...);}bool add(uint64_t uid){/*根据uid获取到玩家的信息*/Json::Value user;bool ret _ut-select_by_id(uid,user);if(retfalse){DLOG(获取玩家:%d 信息失败,uid);return false;}int score user[score].asInt();if(score 2000){_q_normal.push(uid);}else if(score2000 score 3000){_q_normal.push(uid);}else{_q_normal.push(uid);}return true;}bool del(uint64_t uid){Json::Value user;bool ret _ut-select_by_id(uid,user);if(retfalse){DLOG(获取玩家:%d 信息失败,uid);return false;}int score user[score].asInt();if(score2000){_q_normal.remove(uid);}else if(score2000 score3000){_q_hight.remove(uid);}else{_q_super.remove(uid);}return true;}};#endif