根据指定规则生成游戏选项编码实战

入遇到这样的需求

“有不定数量的游戏选项和不定的游戏人数选项给用户选择,我们按照  游戏人数<<24 | 游戏规则A<<16 | 游戏规则B<<8 | 游戏规则C      游戏规则D<<24 | 游戏规则E<<16 | 游戏规则F<<8 | 游戏规则G ........  来生成所有规则可能选中和未选中的游戏码”

该需求中,不定数量的游戏选项和游戏人数需要动态输入  我们需要使用读取配置文件来获取多少游戏人数和游戏规则 这是待实现的功能1

根据获取数量的游戏选项 我们要生成所有可能的选中和未选中的排列组合  这是待实现的功能2

根据生成排列组合按照规则生成游戏码 还要说明游戏码中那些游戏选项被选中,也意味着需要进行排列组合和游戏规则的映射 这是待实现的功能3

读取配置文件来获取多少游戏人数和游戏规则 可以使用状态机分析配置文件 这之前已经有文章进行了介绍

地址 

据获取数量的游戏选项 我们要生成所有可能的选中和未选中的排列组合 可以使用递归回溯来进行计算

整个流程如下

假设游戏规则有三个  游戏规则 A B C 

步骤1 假设游戏规则A 被选中  生成编码1 

步骤2 假设游戏规则B 被选中 生成编码11

步骤3 假设游戏规则C 被选中 生成第一个完整编码111 

我们回退到步骤2 假设游戏规则B 被选中后  步骤3 假设游戏规则C未被选中 生成第二个完整编码 110  以此类推 。。。。。。

流程示意图

整个过程描述比较繁琐 但是对于使用递归回溯的函数 则十分简洁

void fillVecInner(int fillPos, map<int, string>& methodNumName) {
    if (fillPos == method_count) {    //排列组合的位数与游戏选项的数目相同 说明生成了一个完整的排列组合 需要记录或者显示

        for (int i = 0; i < vec.size(); i++) {
            if (1 == vec[i]) {
                std::cout << methodNumName[i] << " ";
            }
        }
        std::cout << std::endl;
        std::cout << std::endl;
        return;
    }

    for (int i = 0; i < 2; i++) {
        vec.push_back(i);    //插入0 或者 1 
        fillVecInner(fillPos + 1, methodNumName);
        vec.pop_back();        //复原 进行下一次的插入
    }
}
View Code

游戏规则名称和生成排列组合的映射就比较简单了  在Cpp里就是一个map容器搞定

void GenmethodCode() {
        int iarr[3] = { 0 };
        for (int i = 0; i < sizeof(iarr) / sizeof(iarr[0]); i++) {
            if (i < vec.size()) {
                iarr[i] = vec[i];
            }
        }
        //打印根据游戏选项生成的游戏码
        Caluateone(player_count, iarr[0], iarr[1], iarr[2]);

        if (vec.size() > 3) {

            int iarr[4] = { 0 };
            for (int i = 0; i < sizeof(iarr) / sizeof(iarr[0]); i++) {
                if (i+3 < vec.size()) {
                    iarr[i] = vec[i+3];
                }
            }
            //打印根据游戏选项生成的游戏码
            Caluatetwo( iarr[0], iarr[1], iarr[2], iarr[3]);
        }
    }
    
View Code
void GenmethodCode() {
        int iarr[3] = { 0 };
        for (int i = 0; i < sizeof(iarr) / sizeof(iarr[0]); i++) {
            if (i < vec.size()) {
                iarr[i] = vec[i];
            }
        }
        //打印根据游戏选项生成的游戏码
        Caluateone(player_count, iarr[0], iarr[1], iarr[2]);

        if (vec.size() > 3) {

            int iarr[4] = { 0 };
            for (int i = 0; i < sizeof(iarr) / sizeof(iarr[0]); i++) {
                if (i+3 < vec.size()) {
                    iarr[i] = vec[i+3];
                }
            }
            //打印根据游戏选项生成的游戏码
            Caluatetwo( iarr[0], iarr[1], iarr[2], iarr[3]);
        }
    }
View Code

全部代码如下

  1 #pragma once
  2 
  3 #include <vector>
  4 #include <iostream>
  5 
  6 using namespace std;
  7 
  8 /*
  9 *作 者: itdef
 10 *欢迎转帖 请保持文本完整并注明出处
 11 *技术博客 http://www.cnblogs.com/itdef/
 12 *技术交流群 群号码:432336863
 13 *欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
 14 *部分老代码存放地点
 15 *http://www.oschina.net/code/list_by_user?id=614253
 16 */
 17 
 18 class GenMethodArray {
 19 public:
 20     GenMethodArray(int MethodCount ,int playerCount):method_count(MethodCount), player_count(playerCount){}
 21     ~GenMethodArray() {}
 22 
 23     void fillVec(int fillPos,  map<int, string>& methodNumName) {
 24         fillVecInner(0, methodNumName);
 25     }
 26     void Caluateone(int playerNum, int j1, int j2, int j3) {
 27         long i1 = 0;
 28 
 29         i1 |= (playerNum << 24);
 30 
 31         i1 |= (j1 << 16);
 32 
 33         i1 |= (j2 << 8);
 34 
 35         i1 |= j3;
 36 
 37         std::cout << std::hex << "first = 0x" << i1 << std::endl;
 38         //std::cout << "first = " << i1 << std::endl;
 39     }
 40 
 41     void Caluatetwo(int j4, int j5, int j6, int j7) {
 42         long i1 = 0;
 43 
 44         i1 |= (j4 << 24);
 45 
 46         i1 |= (j5 << 16);
 47 
 48         i1 |= (j6 << 8);
 49 
 50         i1 |= j7;
 51 
 52         std::cout << std::hex << "tow = 	0x" << i1 << std::endl;
 53         //std::cout << "tow = 	" << i1 << std::endl;
 54     }
 55 
 56     void GenmethodCode() {
 57         int iarr[3] = { 0 };
 58         for (int i = 0; i < sizeof(iarr) / sizeof(iarr[0]); i++) {
 59             if (i < vec.size()) {
 60                 iarr[i] = vec[i];
 61             }
 62         }
 63         //打印根据游戏选项生成的游戏码
 64         Caluateone(player_count, iarr[0], iarr[1], iarr[2]);
 65 
 66         if (vec.size() > 3) {
 67 
 68             int iarr[4] = { 0 };
 69             for (int i = 0; i < sizeof(iarr) / sizeof(iarr[0]); i++) {
 70                 if (i+3 < vec.size()) {
 71                     iarr[i] = vec[i+3];
 72                 }
 73             }
 74             //打印根据游戏选项生成的游戏码
 75             Caluatetwo( iarr[0], iarr[1], iarr[2], iarr[3]);
 76         }
 77     }
 78     
 79 
 80 private:
 81     void fillVecInner(int fillPos, map<int, string>& methodNumName) {
 82         if (fillPos == method_count) {
 83             //打印游戏选项名称 若被选中
 84             for (int i = 0; i < vec.size(); i++) {
 85                 if (1 == vec[i]) {
 86                     std::cout << methodNumName[i] << " ";
 87                 }
 88             }
 89             std::cout << std::endl;
 90 
 91             /*for (int i = 0; i < vec.size(); i++) {
 92                 std::cout << vec[i];
 93             }*/
 94             //此函数中  打印根据游戏选项生成的游戏码
 95             GenmethodCode();
 96             std::cout << std::endl;
 97             std::cout << std::endl;
 98             return;
 99         }
100 
101         for (int i = 0; i < 2; i++) {
102             vec.push_back(i);
103             fillVecInner(fillPos + 1, methodNumName);
104             vec.pop_back();
105         }
106     }
107 
108     int player_count;
109     int method_count;
110     vector<int> vec;
111 };
GenMethodArray.h
 1 #pragma once
 2 #include <iostream>
 3 #include <fstream>
 4 #include <cassert>
 5 #include <string>
 6 #include <iostream>
 7 #include <vector>
 8 #include <map>
 9 
10 using namespace std;
11 
12 /*
13 *作 者: itdef
14 *欢迎转帖 请保持文本完整并注明出处
15 *技术博客 http://www.cnblogs.com/itdef/
16 *技术交流群 群号码:432336863
17 *欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
18 *部分老代码存放地点
19 *http://www.oschina.net/code/list_by_user?id=614253
20 */
21 
22 const string FILE_NAME = "config.txt";
23 
24 class ReadConfig {
25 public:
26     ReadConfig(string filename="") {
27         if (filename.empty()) {
28             file_name = FILE_NAME;
29         }
30         else {
31             file_name = filename;
32         }
33     }
34     ~ReadConfig(){}
35 
36     map<string, string> Do() {
37         tar_path.clear();
38         ifstream fin;
39         fin.open(file_name);
40         if (false == fin.is_open()) {
41             std::cerr << "open file failed!!" << std::endl;
42             return tar_path;
43         }
44         string s;
45 
46         while (getline(fin, s))
47         {
48             if ( '#' == s[0] || ( '/' == s[0]  && '/' == s[1]))
49                 continue;
50             size_t pos = s.find_first_of("=");
51             if (pos == std::string::npos || pos + 1 >= s.size())
52                 continue;
53             string targetName = s.substr(0, pos);
54             string path = s.substr(pos + 1);
55             std::cout << targetName << " = " << path << std::endl;
56             if(path[0] != ' ')
57                 tar_path[targetName] = path;
58         }
59         fin.close();
60 
61         return tar_path;
62     }
63 
64 private:
65     map<string, string> tar_path;
66     string file_name;
67 
68 };
ReadConfig.h
 1 // CalculatePlayMethod.cpp: 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include "ReadConfig.h"
 6 #include "GenMethodArray.h"
 7 
 8 /*
 9 *作 者: itdef
10 *欢迎转帖 请保持文本完整并注明出处
11 *技术博客 http://www.cnblogs.com/itdef/
12 *技术交流群 群号码:432336863
13 *欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
14 *部分老代码存放地点
15 *http://www.oschina.net/code/list_by_user?id=614253
16 */
17 
18 
19 int main()
20 {
21     //获取配置
22     ReadConfig readcf;
23     map<string, string> targetMethod = readcf.Do();
24     if (targetMethod.size() == 0) {
25         std::cerr << "get config error! exit!!" << std::endl;
26         return -1;
27     }
28     
29     //获取玩家人数
30     int playerCount = atoi( targetMethod["playerNum"].c_str());
31     if (0 == playerCount) {
32         playerCount = 4;
33     }
34 
35     //获取玩法编号和玩法名称
36     map<int, string> methodNumName;
37     for (const auto& e : targetMethod) {
38         if (e.first != "playerNum" && e.second != "") {
39             //根据玩法标识最后一位的字符 与 ‘0’ 字符的差值 就是该字符表示的数值
40             //考虑到 数组与实际位值可能差1  所以是- ‘1’ 而不是 - ‘0’
41             int i = (e.first)[e.first.size() - 1] - '1';
42             methodNumName[i] = e.second;
43         }
44     }
45 
46     //生成玩法的排列组合
47     GenMethodArray genMeArr(methodNumName.size(), playerCount);
48     genMeArr.fillVec(0, methodNumName);
49 
50     system("pause");
51     return 0;
52 }
CalculatePlayMethod.cpp

配置文件内容

#注释可以使用 // 或者 #

playerNum=3
playMethod1=游戏模式A
playMethod2=游戏模式B
playMethod3=游戏模式C
playMethod4=游戏模式D
playMethod5=游戏模式E
playMethod6=
playMethod7=
playMethod8=
playMethod9=
//目前仅支持 7种玩法以内配置

运行效果如图

 1 // 1111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 
 4 #include "pch.h"
 5 #include <iostream>
 6 #include <vector>
 7 #include <string>
 8 
 9 
10 using namespace std;
11 
12 vector<vector<int>> init = {
13     {4},{0,1,2},{0,1},{0,1}
14 };
15 vector<string> gv;
16 void findCombination (int index, const string& s) {
17     if (index == 4) {
18         gv.push_back(s);
19         return;
20     }
21     vector<int> v = init[index];
22     for (int i = 0; i < v.size(); i++) {
23         findCombination(index + 1, s + to_string(v[i]));
24     }
25 
26 }
27 int main()
28 {
29     std::cout << "Hello World!
"; 
30     findCombination(0,"");
31     for (int i = 0; i < gv.size(); i++) {
32         std::cout << gv[i] << std::endl;
33     }
34 }
35 
36 // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
37 // 调试程序: F5 或调试 >“开始调试”菜单
38 
39 // 入门提示: 
40 //   1. 使用解决方案资源管理器窗口添加/管理文件
41 //   2. 使用团队资源管理器窗口连接到源代码管理
42 //   3. 使用输出窗口查看生成输出和其他消息
43 //   4. 使用错误列表窗口查看错误
44 //   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
45 //   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
View Code
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
阿里打赏 微信打赏
原文地址:https://www.cnblogs.com/itdef/p/9601940.html