Dota游戏匹配的所有组合
在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游戏匹配的所有组合的更多相关文章
- 编写Java程序,创建Dota游戏中的防御塔类,通过两个坐属性显示防御塔所在的位置
返回本章节 返回作业目录 需求说明: 创建Dota游戏中的防御塔类 通过两个坐属性显示防御塔所在的位置 实现思路: 创建防御塔(TowerDefense)类 在该类中定义了两个属性,分别是int类型横 ...
- 编写Java程序,创建Dota游戏中的兵营类,兵营类有一个类成员变量count、一个实例变量name和另一个实例变量selfCount。
返回本章节 返回作业目录 需求说明: 创建Dota游戏中的兵营类 兵营类有一个类成员变量count.一个实例变量name和另一个实例变量selfCount. count表示的是兵营已经创建士兵的总数: ...
- DOTA游戏相关的文章
DOTA里面到底有几号位?各代表什么? DOTA新手进阶之S.SHIFT及M键的使用 Dota开局 对线方法技巧总结 dota补刀的技巧 dota需要注意的小细节 dota前期如何对线 DotA 命令 ...
- LeetCode 22 Generate Parentheses(找到所有匹配的括号组合)
题目链接 : https://leetcode.com/problems/generate-parentheses/?tab=Description 给一个整数n,找到所有合法的 () pairs ...
- 浅谈公平组合游戏IGC
浅谈公平组合游戏IGC IGC简介 一个游戏满足以下条件时被叫做IGC游戏 (前面三个字是自己YY的,不必在意) 竞争性:两名玩家交替行动. 公平性:游戏进程的任意时刻,可以执行的操作和操作者本人无关 ...
- 【博弈论】组合游戏及SG函数浅析
目录 预备知识 普通的Nim游戏 SG函数 预备知识 公平组合游戏(ICG) 若一个游戏满足: 由两名玩家交替行动: 游戏中任意时刻,合法操作集合只取决于这个局面本身: 若轮到某位选手时,若该选手无合 ...
- C#简单游戏外挂制作(以Warcraft Ⅲ为例)
网上有很多外挂制作的教程,大多是讲针对大型网络游戏的,主要包含一些抓包.反汇编.C++的知识综合.事实也如此,常见的外挂都是使用VC++写的,从来没有过C#或者其他.NET语言编写的外挂. 作为微软. ...
- 淘宝SKU组合查询算法实现
淘宝SKU组合查询算法实现 2015-11-14 16:18 1140人阅读 评论(0) 收藏 举报 分类: JavaScript(14) 目录(?)[+] 前端有多少事情可以做,能做到多 ...
- 游戏AI之感知(1)
目录 感知 视觉感知 听力感知 其它感知 实现 感知 视觉感知 视觉感知是一种常见的感知. 在许多即时战略游戏或者类DOTA游戏里,一个单位的视觉感知往往是圆形范围的. 当然在其他大部分俯视角游戏里, ...
随机推荐
- 为什么要有 Servlet ,什么是 Servlet 容器,什么是 Web 容器?
本文已收录至 https://github.com/yessimida/yes ,这里有我的所有文章分类汇总,欢迎 star! 以下代码相信大家都很熟悉,大学时学 Java Web 都写过这样的代码. ...
- I am zhoukangyang!
我是 \(\texttt{zhoukangyang}\),一名来自浙江省,杭州市的初二菜鸡 \(\texttt{oier}\) . 洛谷zhoukangyang 很多东西因为太垃圾所以 了,要开 请洛 ...
- Day2 之 元组tuple
tuple 元组 也是有序列表 ,与list非常相似,但是tuple一旦初始化就不能修改. name = ('a','b',1,2,3,True) tuple ...
- 学好Spark/Kafka必须要掌握的Scala技术点(三)高阶函数、方法、柯里化、隐式转换
5. 高阶函数 Scala中的高阶函数包含:作为值的函数.匿名函数.闭包.柯里化等,可以把函数作为参数传递给方法或函数. 5.1 作为值的函数 定义函数时格式: val 变量名 = (输入参数类型和个 ...
- 移动端 better-scroll基础
一.什么是better-scroll better-scroll 是一款重点解决移动端(已支持 PC)各种滚动场景需求的插件 #滚动原理 1. 与浏览器滚动原理一致,父容器高度固定,子元素内容撑开,必 ...
- [从源码学设计]蚂蚁金服SOFARegistry 之 自动调节间隔周期性任务
[从源码学设计]蚂蚁金服SOFARegistry 之 自动调节间隔周期性任务 目录 [从源码学设计]蚂蚁金服SOFARegistry 之 自动调节间隔周期性任务 0x00 摘要 0x01 业务领域 0 ...
- Eureka系列(三)获取服务Client端具体实现
获取服务Client 端流程 我们先看下面这张图片,这张图片简单描述了下我们Client是如何获取到Server已续约实例信息的流程: 从图片中我们可以知晓大致流程就是Client会自己开启一个 ...
- Spark性能调优篇八之shuffle调优
1 task的内存缓冲调节参数 2 reduce端聚合内存占比 spark.shuffle.file.buffer map task的内存缓冲调节参数,默认是3 ...
- 保姆级教程,带你认识大数据,从0到1搭建 Hadoop 集群
大数据简介,概念部分 概念部分,建议之前没有任何大数据相关知识的朋友阅读 大数据概论 什么是大数据 大数据(Big Data)是指无法在一定时间范围内用常规软件工具进行捕捉.管理和处理的数据集合,是需 ...
- 第 16 章 【硬核!】 垃圾回收相关 GC细讲
第 16 章 垃圾回收相关概念 1.System.gc() 的理解 1.1.System.gc() 方法 System.gc() 方法 在默认情况下,通过System.gc()者Runtime.get ...