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


    入遇到这样的需求

    “有不定数量的游戏选项和不定的游戏人数选项给用户选择,我们按照  游戏人数<<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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    如何保证access_token长期有效
    微信自定义菜单的创建
    是否同一棵二叉搜索树
    Tree Traversals Again(根据前序,中序,确定后序顺序)
    List Leaves 树的层序遍历
    leetcode-优美的排列
    leetcode-下一个排列
    leetcode-二进制手表
    leetcode-组合总数III(回溯)
    leetcode-累加数(C++)
  • 原文地址:https://www.cnblogs.com/itdef/p/9601940.html
Copyright © 2020-2023  润新知