#include
#include
#include
#include
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 = 1
emMJ_NanFeng = MJ(4, 6),//南 6 % 4 = 2
emMJ_XiFeng = MJ(4, 11),//西 11 % 4 = 3
emMJ_BeiFeng = MJ(4, 16),//北 16 % 4 = 0
emMJ_HongZhong = MJ(4, 18),//中 18 % 4 = 2
emMJ_FaCai = MJ(4, 23),//发 23 % 4 = 3
emMJ_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 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 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& original_pai)
{
//前提:牌已经排好序,不含已碰牌和已杠牌,所以牌数应该是3n+2
//过程:先找出一对将牌,然后再寻找刻子牌和顺子牌,直到剩余牌为0才表示可和牌,否则不能和牌
//记录将牌位置
size_t jiang_location = -1;
std::vector 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 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& 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 Ting(const std::vector& pai)
{
//遍历所有牌,依次加入,判断是否能和牌
std::vector 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 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 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;
}