在Dota游戏中有一种匹配玩法,任意5人以下玩家组队,加入匹配系统,由系统组合出5人 vs 5人的组合进行游戏,比如2人+3人  vs 1人+4人。抽象出这个问题,就变成两边各有m个玩家,最多允许n个人组队(n <= m),计算所有的组合方式。思路是,先考虑单边阵营的组合,比如5人,可以1+4,2+3,1+1+1+1+1...,用递归的方式可以计算出所有的单边阵营组合。将单边阵营的组合两两配对,就获取到双边阵营的组合。假设单边组合有n个,那么双边组合就会有c(n, 2)个。但是这里面会有重复的组合,还得把重复的组合去掉。

void TestLadderRule()
{
#define OUTPUT_INFO printf("input max camp amount and max team amount(e.g. 5 5): "); OUTPUT_INFO; int nCampMbr = 0;
int nMaxTeamMbr = 0;
while (scanf_s("%d %d", &nCampMbr, &nMaxTeamMbr) == 2)
{
LadderRule(nCampMbr, nMaxTeamMbr); OUTPUT_INFO;
}
} // 参数:阵营人数,最多允许组队人数
void LadderRule( int nCampMbr, int nMaxTeamMbr )
{
if (nCampMbr < 1)
return; if (nMaxTeamMbr < 0 || nMaxTeamMbr > nCampMbr)
return; // 单阵营规则
vector< vector<int> > campRules;
// 匹配规则
vector<string> matchRules;
// 已经使用过的匹配规则
set<string> usedRules;
// 用于生成单阵营规则
int *rule = new int[nCampMbr+1];
memset(rule, 0, sizeof(int)*(nCampMbr+1)); // 找出单边阵营的所有规则
int nTeamMbr = 1;
int nSum = 0;
bool bUpAmount = false;
while (true)
{
if (!nTeamMbr)
break; if (nTeamMbr < nMaxTeamMbr)
{
if (bUpAmount)
{
++rule[nTeamMbr];
nSum += nTeamMbr;
bUpAmount = false;
} if (nSum > nCampMbr)
{
nSum -= rule[nTeamMbr] * nTeamMbr;
rule[nTeamMbr] = 0;
--nTeamMbr;
bUpAmount = true;
}
else
{
++nTeamMbr;
}
}
else
{
if ((nCampMbr - nSum) % nMaxTeamMbr == 0)
{
rule[nMaxTeamMbr] = (nCampMbr - nSum) / nMaxTeamMbr; vector<int> tempRule;
for (int i = 1; i <= nCampMbr; ++i)
tempRule.push_back(rule[i]);
campRules.push_back(tempRule);
} rule[nMaxTeamMbr] = 0;
--nTeamMbr;
bUpAmount = true;
}
} // 将单边阵营的规则两两组合,形成匹配规则
for (size_t i = 0; i < campRules.size(); ++i)
{
for (size_t j = i; j < campRules.size(); ++j)
{
// 总的规则
char chRule[1025] = { 0 };
char *chPos = chRule;
int nLength = 1024;
for (int k = 0; k < nCampMbr; ++k)
{
sprintf_s(chPos, nLength, "%2d ", campRules[i][k] + campRules[j][k]);
chPos += 3;
nLength -= 3;
} // 剔除重复的匹配规则
if (usedRules.count(chRule))
continue;
usedRules.insert(chRule); sprintf_s(chPos, nLength, "| ");
chPos += 2;
nLength -= 2; // 左边阵营规则
for (int k = 0; k < nCampMbr; ++k)
{
sprintf_s(chPos, nLength, "%2d ", campRules[i][k]);
chPos += 3;
nLength -= 3;
} sprintf_s(chPos, nLength, "| ");
chPos += 2;
nLength -= 2; // 右边阵营规则
for (int k = 0; k < nCampMbr; ++k)
{
sprintf_s(chPos, nLength, "%2d ", campRules[j][k]);
chPos += 3;
nLength -= 3;
} matchRules.push_back(chRule);
}
} sort(matchRules.begin(), matchRules.end()); printf("match rules' amount: %d\n", matchRules.size());
for (auto it = matchRules.begin(); it != matchRules.end(); ++it)
{
printf("%s\n", it->c_str());
} delete[] rule;
}

代码:https://github.com/windpenguin/WindUtilities

Dota游戏匹配的所有组合的更多相关文章

  1. 编写Java程序,创建Dota游戏中的防御塔类,通过两个坐属性显示防御塔所在的位置

    返回本章节 返回作业目录 需求说明: 创建Dota游戏中的防御塔类 通过两个坐属性显示防御塔所在的位置 实现思路: 创建防御塔(TowerDefense)类 在该类中定义了两个属性,分别是int类型横 ...

  2. 编写Java程序,创建Dota游戏中的兵营类,兵营类有一个类成员变量count、一个实例变量name和另一个实例变量selfCount。

    返回本章节 返回作业目录 需求说明: 创建Dota游戏中的兵营类 兵营类有一个类成员变量count.一个实例变量name和另一个实例变量selfCount. count表示的是兵营已经创建士兵的总数: ...

  3. DOTA游戏相关的文章

    DOTA里面到底有几号位?各代表什么? DOTA新手进阶之S.SHIFT及M键的使用 Dota开局 对线方法技巧总结 dota补刀的技巧 dota需要注意的小细节 dota前期如何对线 DotA 命令 ...

  4. LeetCode 22 Generate Parentheses(找到所有匹配的括号组合)

    题目链接 : https://leetcode.com/problems/generate-parentheses/?tab=Description   给一个整数n,找到所有合法的 () pairs ...

  5. 浅谈公平组合游戏IGC

    浅谈公平组合游戏IGC IGC简介 一个游戏满足以下条件时被叫做IGC游戏 (前面三个字是自己YY的,不必在意) 竞争性:两名玩家交替行动. 公平性:游戏进程的任意时刻,可以执行的操作和操作者本人无关 ...

  6. 【博弈论】组合游戏及SG函数浅析

    目录 预备知识 普通的Nim游戏 SG函数 预备知识 公平组合游戏(ICG) 若一个游戏满足: 由两名玩家交替行动: 游戏中任意时刻,合法操作集合只取决于这个局面本身: 若轮到某位选手时,若该选手无合 ...

  7. C#简单游戏外挂制作(以Warcraft Ⅲ为例)

    网上有很多外挂制作的教程,大多是讲针对大型网络游戏的,主要包含一些抓包.反汇编.C++的知识综合.事实也如此,常见的外挂都是使用VC++写的,从来没有过C#或者其他.NET语言编写的外挂. 作为微软. ...

  8. 淘宝SKU组合查询算法实现

    淘宝SKU组合查询算法实现 2015-11-14 16:18 1140人阅读 评论(0) 收藏 举报  分类: JavaScript(14)    目录(?)[+]   前端有多少事情可以做,能做到多 ...

  9. 游戏AI之感知(1)

    目录 感知 视觉感知 听力感知 其它感知 实现 感知 视觉感知 视觉感知是一种常见的感知. 在许多即时战略游戏或者类DOTA游戏里,一个单位的视觉感知往往是圆形范围的. 当然在其他大部分俯视角游戏里, ...

随机推荐

  1. DeepFM——tensorflow代码改编

    本人代码库: https://github.com/beathahahaha/tensorflow-DeepFM-master-original DeepFM原作者代码库: https://githu ...

  2. (数据科学学习手札99)掌握pandas中的时序数据分组运算

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 我们在使用pandas分析处理时间序列数据 ...

  3. WPF源代码分析系列一:剖析WPF模板机制的内部实现(一)

    众所周知,在WPF框架中,Visual类是可以提供渲染(render)支持的最顶层的类,所有可视化元素(包括UIElement.FrameworkElment.Control等)都直接或间接继承自Vi ...

  4. 学习笔记:舞蹈链 Dancing Links

    这是一种奇妙的算法用来解决两个问题: 精确覆盖问题:给定一个矩阵,每行是一个二进制数,选出尽量少的行,使得每一列恰好有一个 \(1\) 重复覆盖问题:给定一个矩阵,每行是一个二进制数,选出尽量少的行, ...

  5. Codeforces Edu Round 62 A-E

    A. Detective Book 模拟题,有一些细节需要注意. #include <cstdio> #include <iostream> #include <cmat ...

  6. Zabbix 新版微信告警-转载

    Zabbix 新版微信告警 Zabbix可以通过多种方式把告警信息发送到指定人,常用的有邮件,短信报警方式,但是越来越多的企业开始使用zabbix结合微信作为主要的告警方式,这样可以及时有效的把告警信 ...

  7. SpringBoot 拦截器和自定义注解判断请求是否合法

    应用场景举例: 当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释 自定义注解 /** * 对比请求的用户身份是否符合 * @author l ...

  8. Scrapy+Scrapyd+Scrapydweb实现爬虫可视化

    Scrapy+Scrapyd+Scrapydweb实现爬虫可视化 Scrapyd是一个服务,用来运行scrapy爬虫的 它允许你部署你的scrapy项目以及通过HTTP JSON的方式控制你的爬虫 官 ...

  9. 精尽Spring MVC源码分析 - 调式环境搭建

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  10. 深入LUA脚本语言,让你彻底明白调试原理

    这是道哥的第008篇原创 一.前言 上篇文章我们聊了gdb的底层调试机制,明白了gdb是利用操作系统提供的系统信号来调试目标程序的.很多朋友私下留言了,看到能帮助到大家,我心里还是很开心的,其实这也是 ...