C++实现麻将基本听牌胡牌的算法
生活随笔
收集整理的這篇文章主要介紹了
C++实现麻将基本听牌胡牌的算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>enum MajiangType
{emMJType_Wan = 1, //萬emMJType_Tiao = 2, //條emMJType_Tong = 3, //筒emMJType_Zi = 4, //字emMJType_Hua = 5 //花
};constexpr char MJ(char m, char n) {return m << 5 | n;
}inline MajiangType Majiang_Type(char m) {return MajiangType(m >> 5);
}inline char Majiang_Value(char m) {return m & 0x1F;
}enum emMJ:char
{emMJ_1Wan = MJ(emMJType_Wan, 1),emMJ_2Wan = MJ(emMJType_Wan, 2),emMJ_3Wan = MJ(emMJType_Wan, 3),emMJ_4Wan = MJ(emMJType_Wan, 4),emMJ_5Wan = MJ(emMJType_Wan, 5),emMJ_6Wan = MJ(emMJType_Wan, 6),emMJ_7Wan = MJ(emMJType_Wan, 7),emMJ_8Wan = MJ(emMJType_Wan, 8),emMJ_9Wan = MJ(emMJType_Wan, 9),emMJ_1Tiao = MJ(emMJType_Tiao, 1),emMJ_2Tiao = MJ(emMJType_Tiao, 2),emMJ_3Tiao = MJ(emMJType_Tiao, 3),emMJ_4Tiao = MJ(emMJType_Tiao, 4),emMJ_5Tiao = MJ(emMJType_Tiao, 5),emMJ_6Tiao = MJ(emMJType_Tiao, 6),emMJ_7Tiao = MJ(emMJType_Tiao, 7),emMJ_8Tiao = MJ(emMJType_Tiao, 8),emMJ_9Tiao = MJ(emMJType_Tiao, 9),emMJ_1Tong = MJ(emMJType_Tong, 1),emMJ_2Tong = MJ(emMJType_Tong, 2),emMJ_3Tong = MJ(emMJType_Tong, 3),emMJ_4Tong = MJ(emMJType_Tong, 4),emMJ_5Tong = MJ(emMJType_Tong, 5),emMJ_6Tong = MJ(emMJType_Tong, 6),emMJ_7Tong = MJ(emMJType_Tong, 7),emMJ_8Tong = MJ(emMJType_Tong, 8),emMJ_9Tong = MJ(emMJType_Tong, 9),//字牌不能形成順子,所以編碼不能連續,而且有的地方有買碼規則,字牌也根據除以4的余數被分配到了4個方位emMJ_DongFeng = MJ(4, 1),//東 1 % 4 = 1emMJ_NanFeng = MJ(4, 6),//南 6 % 4 = 2emMJ_XiFeng = MJ(4, 11),//西 11 % 4 = 3emMJ_BeiFeng = MJ(4, 16),//北 16 % 4 = 0emMJ_HongZhong = MJ(4, 18),//中 18 % 4 = 2emMJ_FaCai = MJ(4, 23),//發 23 % 4 = 3emMJ_BaiBan = MJ(4, 28),//白 28 % 4 = 0//一副中花牌各只有一張emMJ_Mei = MJ(5, 1),//梅emMJ_Lan = MJ(5, 3),//蘭emMJ_Ju = MJ(5, 5),//菊emMJ_Zhu = MJ(5, 7),//竹emMJ_Chun = MJ(5, 9),//春emMJ_Xia = MJ(5, 11),//夏emMJ_Qiu = MJ(5, 13),//秋emMJ_Dong = MJ(5,15) //冬
};const std::vector<char> all_majiang = {emMJ_1Wan,emMJ_2Wan,emMJ_3Wan,emMJ_4Wan,emMJ_5Wan,emMJ_6Wan,emMJ_7Wan,emMJ_8Wan,emMJ_9Wan,emMJ_1Tiao,emMJ_2Tiao,emMJ_3Tiao,emMJ_4Tiao,emMJ_5Tiao,emMJ_6Tiao,emMJ_7Tiao,emMJ_8Tiao,emMJ_9Tiao,emMJ_1Tong,emMJ_2Tong,emMJ_3Tong,emMJ_4Tong,emMJ_5Tong,emMJ_6Tong,emMJ_7Tong,emMJ_8Tong,emMJ_9Tong,emMJ_DongFeng,emMJ_NanFeng,emMJ_XiFeng,emMJ_BeiFeng,emMJ_BaiBan,emMJ_FaCai,emMJ_HongZhong
};
const std::vector<emMJ> pattern131 = { emMJ_1Wan,emMJ_9Wan,emMJ_1Tiao,emMJ_9Tiao,emMJ_1Tong,emMJ_9Tong,emMJ_DongFeng,emMJ_NanFeng,emMJ_XiFeng,emMJ_BeiFeng,emMJ_HongZhong,emMJ_FaCai,emMJ_BaiBan};//基本和牌類型
bool IsCommonHu(const std::vector<char>& original_pai)
{//前提:牌已經排好序,不含已碰牌和已杠牌,所以牌數應該是3n+2//過程:先找出一對將牌,然后再尋找刻子牌和順子牌,直到剩余牌為0才表示可和牌,否則不能和牌//記錄將牌位置size_t jiang_location = -1;std::vector<char> pai;while (true){auto i = jiang_location + 1;if (i >= original_pai.size()){return false;}pai = original_pai;if (jiang_location != -1){if (pai[i] == pai[jiang_location]){++i;}}//尋找將牌位置,記錄將牌第二個,并擦除該兩牌jiang_location = -1;for (; i < pai.size() - 1; ++ i){if (pai[i] == pai[i + 1]){jiang_location = i + 1;pai.erase(pai.begin() + i, pai.begin() + i + 2);break;}}if (jiang_location == -1){//沒有將牌,不能和牌return false;}//剩下的牌數是3的倍數//從左起第1張牌開始,它必須能組成刻子牌或者順子牌才能和,否則不能和while (pai.size() >= 3){if (pai[0] == pai[1] && pai[0] == pai[2]){//找到刻子牌并移除pai.erase(pai.begin(), pai.begin() + 3);}else{auto it1 = std::find(pai.begin() + 1,pai.end(), pai[0] + 1);if (it1 != pai.end()){auto it2 = std::find(it1 + 1, pai.end(), pai[0] + 2);if (it2 != pai.end()){//找到順子牌并移除pai.erase(it2);pai.erase(it1);pai.erase(pai.begin());}else{break;}}else{break;}}}if (pai.empty()){break;}}return true;
}//是否是十三幺牌型
bool Is131Hu(std::vector<char> original_pai)
{if (original_pai.size() != 14){return false;}size_t i = 0;while (i < original_pai.size()-1){if (original_pai[i] == original_pai[i+1]){break;}++i;}if (i == original_pai.size() - 1){return false;}original_pai.erase(original_pai.begin() + i);if (pai.size() != pattern131.size()){return false;}for (size_t i = 0; i < pai.size(); ++i){if (original_pai.[i] != pattern131[i]) {return false;}}return true;
}//是否是小七對牌型
bool Is7pairsHu(const std::vector<char>& pai) {const int pairs = 7;if (pai.size() != 2 * pairs){return false;}int i = 0;for (; i < pairs; ++i){if (pai[2 * i] != pai[2 * i + 1]){break;}}return i == pairs;
}//檢查聽哪些牌
std::vector<char> Ting(const std::vector<char>& pai)
{//遍歷所有牌,依次加入,判斷是否能和牌std::vector<char> hupai;for (auto& i : all_majiang){auto temp(pai);temp.push_back(i);std::sort(temp.begin(), temp.end()); //先排序if (Is131Hu(temp) || Is7pairsHu(temp) || IsCommonHu(temp)){hupai.push_back(i);}}return hupai;
}int main()
{std::vector<char> v = { MJ(1,2),MJ(1,2),MJ(2,2),MJ(2,2),MJ(1,3),MJ(3,4),MJ(3,4),MJ(1,4),MJ(1,4),MJ(2,5),MJ(2,5),MJ(1,6),MJ(1,6) };std::vector<char> tingpai;auto start = std::chrono::steady_clock::now();tingpai = Ting(v);std::chrono::nanoseconds ns = std::chrono::steady_clock::now() - start;std::cout << "time:" << ns.count() << std::endl;for (auto& i : tingpai){std::cout << "Result:" << (int)i << std::endl;}system("pause");return 0;
}
總結
以上是生活随笔為你收集整理的C++实现麻将基本听牌胡牌的算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GSL----积分部分(翻译+精简)
- 下一篇: 【CSS】笔记3-三大样式、盒子模型、P