在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. bugkuctf web区 sql2

    来了!终于做出来(虽然是在大佬帮助下,提前感谢大佬) 在看wp之后发现这是一道典型的.DS_Store源码泄露,其他类型的web源码泄露:https://www.secpulse.com/archiv ...

  2. 手把手教你写DI_1_DI框架有什么?

    DI框架有什么? 在上一节:手把手教你写DI_0_DI是什么? 我们已经理解DI是什么 接下来我们就徒手撸一撸,玩个支持构造函数注入的DI出来 首先我们回顾一下 构造函数注入 的代码形式, 大概长这模 ...

  3. Windows的API功能查询

    在逆向分析时,一些Windows的API函数往往是我们的突破口.但这些函数很难记得一清二楚,以下是我的查找办法,做个小结. 官网 https://docs.microsoft.com/en-us/wi ...

  4. 五、Zookeeper基于API操作Node节点

    安装zookeeper :linux下安装Zookeeper 3.4.14 zookeeper 分为5个包: org.apache.zookeeper //客户端主要类文件 org.apache.zo ...

  5. PHP表白墙网站源码

    PHP表白墙网站源码,可以做校园内的,也可以做校区间的,可封装成APP.告别QQ空间的表白墙吧. 安装简单,上传程序安装,然后设置账号密码,登陆后台切换模板手机PC都要换开启插件访问前台. 安装完成后 ...

  6. Python最会变魔术的魔术方法,我觉得是它!

    在上篇文章中,我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系. 但是,文中也提到了一个例外:一个非常神秘的魔术方 ...

  7. Greenplum 性能优化之路 --(三)ANALYZE

    一.为什么需要 ANALYZE 首先介绍下 RBO 和 CBO,这是数据库引擎在执行 SQL 语句时的2种不同的优化策略. RBO(Rule-Based Optimizer) 基于规则的优化器,就是优 ...

  8. Kubernetes【K8S】(一):Kubernetes组件

    什么是Kubernetes ​ Kubernetes 是一个可移植的.可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化.Kubernetes拥有一个庞大且快速增长的生态系统. ...

  9. 微服务开发的最大痛点-分布式事务SEATA入门简介

    前言 在微服务开发中,存在诸多的开发痛点,例如分布式事务.全链路跟踪.限流降级和服务平滑上下线等.而在这其中,分布式事务是最让开发者头痛的.那分布式事务是什么呢? 分布式事务就是指事务的参与者.支持事 ...

  10. Hive中的集合数据类型

    除了使用础的数据类型string等,Hive中的列支持使用struct, map, array集合数据类型. 数据类型 描述 语法示例 STRUCT 和C语言中的struct或者"对象&qu ...