入遇到這樣的需求ios
「有不定數量的遊戲選項和不定的遊戲人數選項給用戶選擇,咱們按照 遊戲人數<<24 | 遊戲規則A<<16 | 遊戲規則B<<8 | 遊戲規則C 遊戲規則D<<24 | 遊戲規則E<<16 | 遊戲規則F<<8 | 遊戲規則G ........ 來生成全部規則可能選中和未選中的遊戲碼」c++
該需求中,不定數量的遊戲選項和遊戲人數須要動態輸入 咱們須要使用讀取配置文件來獲取多少遊戲人數和遊戲規則 這是待實現的功能1程序員
根據獲取數量的遊戲選項 咱們要生成全部可能的選中和未選中的排列組合 這是待實現的功能2windows
根據生成排列組合按照規則生成遊戲碼 還要說明遊戲碼中那些遊戲選項被選中,也意味着須要進行排列組合和遊戲規則的映射 這是待實現的功能3數組
讀取配置文件來獲取多少遊戲人數和遊戲規則 能夠使用狀態機分析配置文件 這以前已經有文章進行了介紹服務器
地址 ide
據獲取數量的遊戲選項 咱們要生成全部可能的選中和未選中的排列組合 能夠使用遞歸回溯來進行計算函數
整個流程以下編碼
假設遊戲規則有三個 遊戲規則 A B C lua
步驟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(); //復原 進行下一次的插入 } }
遊戲規則名稱和生成排列組合的映射就比較簡單了 在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]); } }
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]); } }
所有代碼以下
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 = \t0x" << i1 << std::endl; 53 //std::cout << "tow = \t" << 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 };
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 };
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 }
配置文件內容
#註釋能夠使用 // 或者 #
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!\n"; 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 文件