求C++实现Mastermind算法的递归n位密码池生成方案
解决Mastermind通用密码池生成问题
首先,咱们先看看你递归代码里的几个问题:
- 循环遍历的是
0到n-1,但实际上应该遍历颜色的取值范围(0到5),因为每个位置的颜色是0-5,和n无关 - 你把
s声明成了const string&,但递归过程中需要修改它来拼接字符,这会导致编译错误 - 递归结束后不需要
clear(),而且每次递归调用后没有回溯(把刚才加的字符删掉),会导致字符串一直累加变长 - 函数没有处理非base case的返回值,会导致未定义行为
下面给你两个可行的实现方案,一个是修正后的递归版本,另一个是迭代版本,你可以根据需求选择:
方案1:修正后的递归实现
这个版本会正确遍历每个位置的颜色(0-5),并且处理好递归的回溯和字符串修改:
#include <vector> #include <string> // 定义颜色数量,Mastermind里是6种(0-5) const int COLOURS = 6; void fillPoolHelper(int remainingLength, std::string current, std::vector<std::string>& pool) { // 基准情况:剩余长度为0,把当前组合加入池 if (remainingLength == 0) { pool.push_back(current); return; } // 遍历所有颜色选项 for (int i = 0; i < COLOURS; ++i) { // 拼接当前颜色字符,递归处理剩余长度 fillPoolHelper(remainingLength - 1, current + std::to_string(i), pool); // 这里不需要手动回溯,因为我们传递的是current的副本,不是引用 } } std::vector<std::string> createPool(int n) { std::vector<std::string> pool; fillPoolHelper(n, "", pool); return pool; }
这里用了一个辅助函数来处理递归逻辑,主函数createPool负责初始化。因为每次递归传递的是current的副本,所以不需要手动回溯,代码更简洁。
方案2:迭代实现
如果递归不是你的首选,也可以用迭代的方式生成所有组合,本质是生成6^n种排列:
#include <vector> #include <string> const int COLOURS = 6; std::vector<std::string> createPool(int n) { std::vector<std::string> pool; // 初始化池:n=1时的所有组合 for (int i = 0; i < COLOURS; ++i) { pool.push_back(std::to_string(i)); } // 逐步构建长度为2到n的组合 for (int length = 2; length <= n; ++length) { std::vector<std::string> newPool; // 把现有每个组合和每个颜色拼接 for (const auto& s : pool) { for (int i = 0; i < COLOURS; ++i) { newPool.push_back(s + std::to_string(i)); } } pool = std::move(newPool); } return pool; }
这个方法从长度1开始,每次把现有所有组合和每个颜色拼接,直到达到目标长度n,逻辑直观,也避免了递归的栈开销(虽然n一般很小,栈开销可以忽略)。
测试验证
比如当n=2时,两个方案都会生成["00","01","02","03","04","05","10","11",..."55"]这样的组合,和预期一致;n=4时就会生成你之前createPool4的所有结果。
内容的提问来源于stack exchange,提问作者Donko
相关产品推荐
相关产品推荐

