从去年年底开始,dota自走旗火了。国产手游厂商纷纷效仿,都想在手游上分一杯羹。我们自然也不例外,只可惜曾经还不错的数据已经快要被梦塔防、龙渊代理的快冲击完了,其实主要还是自己作死了一波。作为程序,还是把其中一些机制总结一下。

房间匹配机制:目前的匹配机制是,按照房间匹配,也就是说,当玩家自由匹配的时候,会查找仍然有空位的房间,将玩家放进去,但是目前侠客的匹配机制有一点有待优化,如果玩家首先点击自有匹配,此时服务器上没有空余房间,将为玩家创建一个房间,这个房间只有该玩家一个人。此时另一个之前创建好的房间点击开始匹配,并不会将这两个房间的玩家合并到一个房间。虽然对于玩家这样的操作是不可见的,但是对于服务器程序来说,心里还是有个梗的。

解决方法:在匹配检测的地方,增加一个匹配预处理的函数,该函数的主要功能就是将玩家聚拢。

实现方法:开辟一个数组,数组每个元素是一个set。遍历两次所有玩家房间的集合,第一次将所有玩家房间按照人数放进我们开辟的数组当中,这样得到的就是:vector<set<uint>>  vector的下标就是对应玩家数量,set集合中就是这些玩家数量的房间的集合,如下图。第二步,处理这个数组。

①两个位置标量,一个从数组头开始,一个从数组尾开始。

②两个标量的房间人数相加,大于最大房间人数,最大标量减一。等于最大房间人数,合并。小于最大房间人数,合并,然后最大房间人数减去合并完的房间人数,再去找剩余人数的下标的集合是否有房间,有的话,刚好合并完这三个房间就是房间最大人数。此处存在一个优化点,最大房间人数减去合并完的房间人数,应该扫描多次。因为如果极端情况,房间人数全是1。

③合并房间人数,删除,插入。

处理代码:

因为代码是在内网,外网就将该模块抽出来,写了个简单例子,可以正常运行,但是没有大量测试,还是主要看思路吧。

#ifndef _MATCH_H_
#define _MATCH_H_#include <map>
#include <set>
#include <list>
#include <time.h>
#include <vector>
#include <iostream>
using namespace std;
#define MAX_ROOM_NUM 3
#define uint unsigned intenum ROOM_TYPE
{ROOM_PUBLIC = 1,ROOM_PRIVATE = 2,
};class CTime
{
public:static CTime &getMe(){if (NULL == instance){instance = new CTime();if (NULL == instance)exit(1);}return *instance;}uint getNowTime(){time_t tmp;time(&tmp);return (uint)tmp;}uint getThisId(){uint uiNowSec = getNowTime();if (uiNowSec != uiBeforeTime){uiBeforeTime = uiNowSec;uiMaxNumSec = 0;}return (uiBeforeTime << 14) + (++uiMaxNumSec);}
private://上一次时间戳uint uiBeforeTime;//每秒最大累加数uint uiMaxNumSec;static CTime *instance;CTime():uiBeforeTime(0), uiMaxNumSec(0){}
};
struct CRoom
{uint uiRoomNum;uint uiCreateTime;uint uiRoomType;std::multiset<uint> setRoomMember;CRoom(uint uiRoomtype = ROOM_PUBLIC){uiRoomType = uiRoomtype;uiRoomNum = CTime::getMe().getThisId();uiCreateTime = CTime::getMe().getNowTime();}
};
class CMatchManager
{
public:static CMatchManager &getMe(){if (NULL == instance){instance = new CMatchManager();if (NULL == instance){exit(1);}}return *instance;}uint createRoomPub(uint uiCreateId){//不在房间if (m_mapUserRoom.find(uiCreateId) != m_mapUserRoom.end()){return 0;}CRoom croom(ROOM_PUBLIC);croom.setRoomMember.insert(uiCreateId);m_mapWaitingRoom.insert(std::make_pair(croom.uiRoomNum, croom));m_mapUserRoom.insert(std::make_pair(uiCreateId, croom.uiRoomNum));std::cout << "create publicroom success,user:" << uiCreateId << ",room:" << croom.uiRoomNum << std::endl;return croom.uiRoomNum;}uint createRoomPri(uint uiCreateId){if (m_mapUserRoom.find(uiCreateId) != m_mapUserRoom.end()){return 0;}CRoom croom(ROOM_PRIVATE);croom.setRoomMember.insert(uiCreateId);m_mapWaitingRoom.insert(std::make_pair(croom.uiRoomNum, croom));m_mapUserRoom.insert(std::make_pair(uiCreateId, croom.uiRoomNum));std::cout << "create privateroom success,user:" << uiCreateId << ",room:" << croom.uiRoomNum << std::endl;return croom.uiRoomNum;}void intoRoomByRoomId(uint uiRoomid, uint uiRoleid){if (m_mapUserRoom.find(uiRoleid) != m_mapUserRoom.end()){std::cout << "error: user have room" << std::endl;return;}auto it = m_mapWaitingRoom.find(uiRoomid);if (it == m_mapWaitingRoom.end()){std::cout << "error: into room error" << std::endl;return;}it->second.setRoomMember.insert(uiRoleid);}void changeRoomType(uint uiRoomid, uint uiRoleid, ROOM_TYPE type){auto it = m_mapWaitingRoom.find(uiRoomid);if (it == m_mapWaitingRoom.end()){std::cout << "error: room not exists" << std::endl;return;}if (0 == (uint)it->second.setRoomMember.size()){std::cout << "error: room number size is 0" << std::endl;return;}if (uiRoleid != *(it->second.setRoomMember.begin())){std::cout << "error: you aren't room creater" << std::endl;return;}it->second.uiRoomType = type;}void beginMatch(uint uiRoleid){//是否有房间auto it = m_mapUserRoom.find(uiRoleid);if (it == m_mapUserRoom.end()){if (m_setMatchingUser.find(uiRoleid) == m_setMatchingUser.end()){m_setMatchingUser.insert(uiRoleid);}}else{auto itroom = m_mapWaitingRoom.find(it->second);if (itroom == m_mapWaitingRoom.end()){std::cout << "error: room not exists" << std::endl;}//private房间else if (ROOM_PRIVATE == itroom->second.uiRoomType){if (1 < (uint)itroom->second.setRoomMember.size()){beginGameWaiting(itroom);}}//房间人数已满else if (MAX_ROOM_NUM <= (uint)itroom->second.setRoomMember.size()){beginGameWaiting(itroom);}//未满 匹配else{m_mapMatchingRoom.insert(std::make_pair(itroom->second.uiRoomNum, itroom->second));m_mapWaitingRoom.erase(itroom++);}}checkMatch();}void checkMatch(){//房间优先auto it = m_mapMatchingRoom.begin();for (; it != m_mapMatchingRoom.end(); ++it){if (ROOM_PRIVATE == it->second.uiRoomType){beginGameMatching(it);continue;}if (MAX_ROOM_NUM <= (uint)it->second.setRoomMember.size()){beginGameMatching(it);continue;}if (m_setMatchingUser.empty()){break;}bool bFlag = false;auto ituser = m_setMatchingUser.begin();for (; ituser != m_setMatchingUser.end(); ){it->second.setRoomMember.insert(*ituser);m_setMatchingUser.erase(ituser++);if (MAX_ROOM_NUM <= (uint)it->second.setRoomMember.size()){beginGameMatching(it);bFlag = true;break;}}if (bFlag)break;}if(it == m_mapMatchingRoom.end()){//查找玩家集合,合并while (MAX_ROOM_NUM <= (uint)m_setMatchingUser.size()){CRoom croom(ROOM_PUBLIC);int i = 0;for (auto ittmp = m_setMatchingUser.begin(); i < MAX_ROOM_NUM && ittmp != m_setMatchingUser.end(); ++i){croom.setRoomMember.insert(*ittmp);m_setMatchingUser.erase(ittmp++);}beginGame(croom);}}else{/////开辟数组,每个元素是对应下标房间人数的集合,然后两个下标,一个前一个后,//优先合并相加等于房间最大人数的多个房间,剩余的,可以合并则合并/////查找多个房间,合并    vector<set<roomid>>std::vector<std::multiset<uint>> veTmp;for (int i = 0; i < MAX_ROOM_NUM; ++i){std::multiset<uint> setTmp;veTmp.push_back(setTmp);}for (it = m_mapMatchingRoom.begin(); it != m_mapMatchingRoom.end(); ){if (it->second.setRoomMember.empty()){m_mapMatchingRoom.erase(it++);}else{veTmp[(uint)it->second.setRoomMember.size() - 1].insert(it->second.uiRoomNum);++it;}}//Begin和End前后相向走,遇到合适的就合并std::vector<std::vector<uint>> vecComRoom;uint uiBegin = 0;uint uiEnd = MAX_ROOM_NUM - 1;while (uiBegin < uiEnd){while (uiBegin < uiEnd && veTmp[uiBegin].empty()) uiBegin++;if (uiBegin >= uiEnd) break;while (uiBegin < uiEnd && veTmp[uiEnd].empty()) uiEnd--;if (uiBegin >= uiEnd) break;if (uiBegin + uiEnd > MAX_ROOM_NUM){uiEnd--;continue;}else if (uiBegin + uiEnd == MAX_ROOM_NUM){for (auto itbegin = veTmp[uiBegin].begin(); itbegin != veTmp[uiBegin].end(); ){auto itend = veTmp[uiEnd].begin();if (itend != veTmp[uiEnd].end()){std::vector<uint> vec;vec.push_back(*itend);vec.push_back(*itbegin);veTmp[uiBegin].erase(itbegin++);veTmp[uiEnd].erase(itend++);vecComRoom.push_back(vec);}else{++itbegin;}}}else{for (auto itbegin = veTmp[uiBegin].begin(); itbegin != veTmp[uiBegin].end(); ){auto itend = veTmp[uiEnd].begin();if (itend != veTmp[uiEnd].end()){std::vector<uint> vec;vec.push_back(*itend);vec.push_back(*itbegin);veTmp[uiBegin].erase(itbegin++);veTmp[uiEnd].erase(itend++);//查找最后符合的uint uiSub = MAX_ROOM_NUM - uiBegin - uiEnd;auto itsub = veTmp[uiSub].begin();if (itsub != veTmp[uiSub].end()){vec.push_back(*itsub);}vecComRoom.push_back(vec);}else{++itbegin;}}}}if (0 < uiBegin && uiBegin <= MAX_ROOM_NUM / 2 && !veTmp[uiBegin].empty()){uint uiNum = 0;std::vector<uint> vec;for (auto it = veTmp[uiBegin].begin(); it != veTmp[uiEnd].end(); ++it){if (2 == uiNum){vecComRoom.push_back(vec);vec.clear();uiNum = 0;}vec.push_back(*it);uiNum += 1;}if (!vec.empty()){vecComRoom.push_back(vec);}}/*//前后先查找一遍,将符合的提出来,然后在走一遍,每次叠加,找到叠加值的互补值for (uint i = 0; i < MAX_ROOM_NUM; ++i){if (veTmp[i].empty()){continue;}if (veTmp[MAX_ROOM_NUM - i - 1].empty()){continue;}auto itroomfirst = veTmp[i].begin();auto itroomsecond = veTmp[MAX_ROOM_NUM - i - 1].begin();while (itroomfirst != veTmp[i].end() && itroomsecond != veTmp[MAX_ROOM_NUM - i - 1].end()){uint uitmpfirst = *itroomfirst;auto ittmpfirst = m_mapMatchingRoom.find(uitmpfirst);uint uitmpsecond = *itroomsecond;auto ittmpsecond = m_mapMatchingRoom.find(uitmpsecond);if (ittmpfirst == m_mapMatchingRoom.end() || ittmpsecond == m_mapMatchingRoom.end()){continue;}}}*/mergeRoom(vecComRoom);}}void mergeRoom(std::vector<std::vector<uint>> &vecComRoom){for (uint dwI = 0; dwI < vecComRoom.size(); ++dwI){uint uiRoomid = (uint)-1;for (uint dwJ = 0; dwJ < vecComRoom[dwI].size(); ++dwJ){if ((uint)-1 == uiRoomid){uiRoomid = vecComRoom[dwI][dwJ];continue;}auto it = m_mapMatchingRoom.find(uiRoomid);auto ittmp = m_mapMatchingRoom.find(vecComRoom[dwI][dwJ]);if (it == m_mapMatchingRoom.end() || ittmp == m_mapMatchingRoom.end()){break;}for (auto itnow = ittmp->second.setRoomMember.begin(); itnow != ittmp->second.setRoomMember.end(); ++itnow){auto itindex = m_mapMatchingRoom.find(*itnow);if (itindex == m_mapMatchingRoom.end()){return;}m_mapMatchingRoom.erase(itindex);it->second.setRoomMember.insert(*itnow);}}}}//beginGamevoid beginGameWaiting(std::map<uint, CRoom>::iterator &itroom){if (itroom != m_mapWaitingRoom.end()){std::cout << "into game success" << std::endl;std::cout << "-------------------" << std::endl;for (auto &it : itroom->second.setRoomMember){cout << "user: " << it << endl;}std::cout << "-------------------" << std::endl;itroom = m_mapWaitingRoom.erase(itroom);}}void beginGameMatching(std::map<uint, CRoom>::iterator &itroom){if (itroom != m_mapMatchingRoom.end()){std::cout << "into game success" << std::endl;std::cout << "-------------------" << std::endl;for (auto &it : itroom->second.setRoomMember){cout << "user: " << it << endl;}std::cout << "-------------------" << std::endl;itroom = m_mapMatchingRoom.erase(itroom);}}std::multiset<uint>::iterator beginGame(std::multiset<uint>::iterator ituser){if (ituser != m_setMatchingUser.end()){std::cout << "into game success" << std::endl;std::cout << "-------------------" << std::endl;cout << "user: " << *ituser << endl;std::cout << "-------------------" << std::endl;m_setMatchingUser.erase(ituser++);}return ituser;}void beginGame(CRoom &croom){std::cout << "into game success" << std::endl;std::cout << "-------------------" << std::endl;for (auto &it : croom.setRoomMember){cout << "user: " << it << endl;}std::cout << "-------------------" << std::endl;}
private://正在匹配房间 <roomid, room>std::map<uint, CRoom> m_mapMatchingRoom;//<userid, roomid>std::map<uint, uint> m_mapUserRoom;//未匹配房间  <roomid, room>std::map<uint, CRoom> m_mapWaitingRoom;//玩家等待列表std::multiset<uint> m_setMatchingUser;static CMatchManager *instance;CMatchManager() {}
};#endif // !_MATCH_H_

测试文件:

#include "match.h"
#include <iostream>
using namespace std;
CTime *CTime::instance = NULL;
CMatchManager *CMatchManager::instance = NULL;#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <math.h>
using namespace std;
int main()
{uint uiRoomid = CMatchManager::getMe().createRoomPri(10);CMatchManager::getMe().beginMatch(10);CMatchManager::getMe().intoRoomByRoomId(uiRoomid, 11);CMatchManager::getMe().beginMatch(10);CMatchManager::getMe().createRoomPub(12);CMatchManager::getMe().beginMatch(12);CMatchManager::getMe().beginMatch(13);CMatchManager::getMe().beginMatch(14);//for (uint i = 10; i < 30; ++i){//CMatchManager::getMe().beginMatch(i);}return 0;
}

关于侠客自走旗,前两个月,数据都还可以。现在如此情景,其实挺遗憾的,但是也不遗憾。毕竟对于我而言,并不遗憾。

房间匹配机制--自走旗相关推荐

  1. 侠客自走旗 -- 到底是海量自走旗中的昙花一现还是困局当中的破茧成蝶?

    大约从去年年底开始,巨鸟多多工作室的dota自走旗也是火了一把.正是如此,国内手游厂商从今年开始陆续发力,APP.H5.亦或是各种游戏副本,各大厂商也是八仙过海,各显一把神通.         从二月 ...

  2. 符号库匹配不对的原因_王者荣耀:万恶的游戏匹配机制,最菜的队友才是游戏胜利的关键...

    在王者荣耀中排位是我们很多玩家的追求,不过在游戏中,因为排位上不去从此的退出游戏的,也是大有人在.一个游戏有新玩家进入,有老玩家离去是一个游戏正常的生态,不过很多因为上不了段位退出游戏的玩家,并且是因 ...

  3. java实现王者荣耀匹配规则,王者荣耀匹配机制(通俗版)

    玩了这么久的王者荣耀,也该出来分析一波了. 很多人都会有这样的疑问:为什么我们在"农药"游戏中会出现连胜之后连败的情况?而且在连胜后遇到的对手都异常强劲,而队友却无比"坑 ...

  4. java顺风车匹配_嘀嗒顺风车以“信息匹配六步走”的模式保障“真顺风”

    顺风车初衷就是为车乘双方节俭出行成本,属于互助模式.随着大众对于顺风车的认可,慢慢的顺风车用户规模增长越来越大,如今顺风车在人们的心中属于一种必选的出门方式,现在有很多的顺风车车主也习惯了于出行的时候 ...

  5. linux内核的I2C子系统详解3——i2c-core.c初步分析、I2C总线的匹配机制

    以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 5.i2c-core.c初步分析 (1)smbus代码略过:smbus是基于I2C总线发展出来的. (2)模块加载和卸 ...

  6. 什么是ACL访问控制列表?它们的匹配机制是什么?

      什么是ACL?        ACL,是Access Control List的简写,中文名称叫做"访问控制列表".访问控制列表(ACL)是一种基于包过滤的访问控制技术,它可以 ...

  7. java游戏房间匹配_一种游戏房间匹配方法与流程

    本发明涉及计算机技术领域,尤其涉及一种游戏房间匹配方法. 背景技术: 在目前的网络游戏中,游戏对象与游戏对象会通过互联网在线上进行竞技比赛,很多时候都需要多名玩家共同参与,现有的游戏对象的配对方法大多 ...

  8. 有房间匹配和无房间匹配

    有房间匹配和无房间匹配 (金庆的专栏 2020.4) 网游的匹配可以分为2种:有房间匹配和无房间匹配. 有房间匹配 请求匹配即搜索并加入一个房间,或者开一个新房间. 匹配过程中可以看到房间人数增加. ...

  9. 游戏思考系列03:游戏匹配机制(MMR、ELO、trueskill2、皇家战争、Glicko等,详细讲ELO,其他的简略)

    文章目录 一.MMR机制--炉石传说.DOTA2.LOL.LOLM 1)简介 2)影响因素 二.ELO机制--王者/LOLM(也就是LOL手游) 1)简介 三.trueskill 2--光环.彩虹六号 ...

  10. 简析王者荣耀的匹配机制

    本文以王者荣耀为主体,结合多款MOBA类游戏,对其匹配机制进行的一些猜想, 1.匹配机制的基础 分别从why.who.how三个角度简析. 1.1Why 王者荣耀有实战对抗模式,娱乐模式,排位赛模式等 ...

最新文章

  1. 如何高效地逛Github?
  2. Java框架JSON-RPC项目demo代码实战 + JAVA WEB配置虚拟目录(转自21天java web开发)
  3. jquery中not方法失效的解决方案
  4. java王子救公主的游_计蒜客 王子救公主(DFS)
  5. 微软自拍:让黑科技拯救不会拍照的你
  6. 7年Java后端被淘汰,一路北漂辛酸史。。。
  7. 数据结构-串操作应用之词索引表
  8. requests用法
  9. 解决chrome和firefox flash不透明的方法
  10. 2019年6月19日Jerry Wang的SAP SAP Cloud Connector练习
  11. C++ 通讯录设计(五)
  12. C# GridView 分页显示
  13. 设计模式之Interpreter(解释器)
  14. linux 有个文件删不掉,Linux下删除不掉的文件
  15. 如何使用小米手机对文档进行扫描
  16. 5G时代的到来会对UI交互设计产生什么影响?
  17. 零代码上线小布对话技能:技能平台的实践与思考
  18. 夏令营导师自荐信计算机专业,北大夏令营的自荐信
  19. 乐视android用流量,乐视max2怎么使用手机用流量上网
  20. Java中的equals和==比较

热门文章

  1. 电池、电机、螺旋桨搭配
  2. 基于windows的源地址路由
  3. 台式计算机上的fn键是哪个,电脑键盘上Fn键到底有什么用?
  4. 同或门真值表_三输入异或门真值表计算详解
  5. STM32硬核DIY机械键盘|蓝牙USB双模|灯控
  6. PDF.js 在线pdf阅读插件(禁止打印,下载,每页水印)
  7. (转贴)联想员工亲历联想大裁员:公司不是家
  8. 信度系数低怎么办?信度系数具体怎么算?
  9. 李阳疯狂英语助教工作总结
  10. oracle访问syno,[Oracle]同义词(synonym)