玩家匹配是根據(jù)自己的天梯分?jǐn)?shù)進(jìn)行匹配的,而服務(wù)器中將玩家天梯分?jǐn)?shù)分為三個(gè)檔次:
1. 普通:天梯分?jǐn)?shù)小于2000分
2. 高手:天梯分?jǐn)?shù)介于2000~3000分之間
3. 大神:天梯分?jǐn)?shù)大于3000分
當(dāng)玩家進(jìn)行對(duì)戰(zhàn)匹配時(shí),服務(wù)器會(huì)根據(jù)檔次,將玩家送到不同檔次的匹配隊(duì)列當(dāng)中。共有3個(gè)匹配隊(duì)列,分別是普通隊(duì)列、高手隊(duì)列和大神隊(duì)列,每一條隊(duì)列由單獨(dú)的線程去控制。因此,匹配對(duì)戰(zhàn)模塊,需要由兩個(gè)類,一個(gè)類是匹配隊(duì)列的類,另外一個(gè)是管理匹配隊(duì)列的類。
匹配隊(duì)列類
當(dāng)玩家進(jìn)行匹配對(duì)戰(zhàn)的請(qǐng)求后,服務(wù)器會(huì)將玩家添加至相應(yīng)的匹配隊(duì)列當(dāng)中,匹配成功后,會(huì)從匹配隊(duì)列中移除該玩家,而在匹配成功前,玩家可能會(huì)中止匹配。因此,匹配隊(duì)列應(yīng)該包含的功能有入隊(duì)、出隊(duì)、和移除指定玩家,玩家處在的位置可能是隊(duì)列的中間,因此,匹配隊(duì)列采用的是雙向循環(huán)鏈表。在匹配過(guò)程中,如果暫時(shí)為達(dá)到匹配玩家個(gè)數(shù),該線程會(huì)進(jìn)入阻塞等待狀態(tài),因此需要實(shí)現(xiàn)的功能還有阻塞等待的方法,獲取隊(duì)列元素個(gè)數(shù)、判斷隊(duì)列是否為空的方法。
template<class T>
class match_queue
{
private:
/*由于可能要?jiǎng)h除中間數(shù)據(jù),因此使用雙向鏈表,而不使用隊(duì)列*/
std::list<T> _list;
//保證線程安全
std::mutex _mutex;
//使用條件變量實(shí)現(xiàn)阻塞,在隊(duì)列中元素個(gè)數(shù)小于2的時(shí)候進(jìn)行阻塞
std::condition_variable _cond;
public:
/*入隊(duì)*/
void push(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
_list.push_back(data);
/*每次有玩家進(jìn)入匹配隊(duì)列后,喚醒線程*/
_cond.notify_all();
}
/*出隊(duì)*/
bool pop(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
if(_list.empty()==true)
{
return false;
}
data = _list.front();
_list.pop_front();
return true;
}
/*移除指定元素*/
void remove(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
_list.remove(data);
}
/*獲取隊(duì)列元素個(gè)數(shù)*/
int size()
{
std::unique_lock<std::mutex> lock(_mutex);
return _list.size();
}
/*判斷隊(duì)列是否為空*/
bool empty()
{
std::unique_lock<std::mutex> lock(_mutex);
return _list.empty();
}
/*阻塞等待*/
void wait()
{
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock);
}
};
匹配隊(duì)列管理類
在匹配隊(duì)列管理類中,創(chuàng)建三個(gè)線程,每一個(gè)線程分別管理著每一條匹配隊(duì)列:
普通線程管理普通隊(duì)列,高手線程管理高手隊(duì)列,大神線程管理大神隊(duì)列。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-636197.html
而管理的方法是:實(shí)現(xiàn)匹配對(duì)戰(zhàn):當(dāng)玩家數(shù)量小于2時(shí),線程繼續(xù)阻塞。大于2時(shí),將兩個(gè)玩家出隊(duì),然后將玩家添加到房間,最后對(duì)玩家進(jìn)行一個(gè)匹配成功的響應(yīng)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-636197.html
#ifndef __M__MATCHER_H__
#define __M__MATCHER_H__
#include<list>
#include <mutex>
#include <condition_variable>
#include "room.hpp"
template<class T>
class match_queue
{
private:
/*由于可能要?jiǎng)h除中間數(shù)據(jù),因此使用雙向鏈表,而不使用隊(duì)列*/
std::list<T> _list;
//保證線程安全
std::mutex _mutex;
//使用條件變量實(shí)現(xiàn)阻塞,在隊(duì)列中元素個(gè)數(shù)小于2的時(shí)候進(jìn)行阻塞
std::condition_variable _cond;
public:
/*入隊(duì)*/
void push(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
_list.push_back(data);
/*每次有玩家進(jìn)入匹配隊(duì)列后,喚醒線程*/
_cond.notify_all();
}
/*出隊(duì)*/
bool pop(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
if(_list.empty()==true)
{
return false;
}
data = _list.front();
_list.pop_front();
return true;
}
/*移除指定元素*/
void remove(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
_list.remove(data);
}
/*獲取隊(duì)列元素個(gè)數(shù)*/
int size()
{
std::unique_lock<std::mutex> lock(_mutex);
return _list.size();
}
/*判斷隊(duì)列是否為空*/
bool empty()
{
std::unique_lock<std::mutex> lock(_mutex);
return _list.empty();
}
/*阻塞等待*/
void wait()
{
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock);
}
};
class matcher
{
private:
/*普通隊(duì)列*/
match_queue<uint64_t> _q_normal;
/*高手隊(duì)列*/
match_queue<uint64_t> _q_hight;
/*大神隊(duì)列*/
match_queue<uint64_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_queue<uint64_t>& mq)
{
while(1)
{
/*判斷隊(duì)列中玩家個(gè)數(shù)是否大于2*/
while(mq.size()<2)
{
mq.wait();
}
/*大于2,將兩個(gè)玩家出隊(duì)*/
uint64_t uid1,uid2;
bool ret = mq.pop(uid1);
if(ret==false)
{
continue;
}
ret = mq.pop(uid2);
if(ret==false)
{
continue;
}
/*兩個(gè)玩家出隊(duì)后,獲取對(duì)應(yīng)的通信連接,然后判斷是否依然連接在線*/
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;
}
/*獲取連接后,為他們創(chuàng)建房間并且添加進(jìn)房間*/
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)
{
/*根據(jù)uid,獲取到玩家的信息*/
Json::Value user;
bool ret = _ut->select_by_id(uid,user);
if(ret==false)
{
DLOG("獲取玩家:%d 信息失敗",uid);
return false;
}
int score = user["score"].asInt();
if(score < 2000)
{
_q_normal.push(uid);
}
else if(score>=2000 && 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(ret==false)
{
DLOG("獲取玩家:%d 信息失敗",uid);
return false;
}
int score = user["score"].asInt();
if(score<2000)
{
_q_normal.remove(uid);
}
else if(score>=2000 && score<3000)
{
_q_hight.remove(uid);
}
else
{
_q_super.remove(uid);
}
return true;
}
};
#endif
到了這里,關(guān)于C++項(xiàng)目:在線五子棋對(duì)戰(zhàn)網(wǎng)頁(yè)版--匹配對(duì)戰(zhàn)模塊開(kāi)發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!