C 帶賴子的麻將聽牌檢測演算法實現

2021-08-07 20:41:42 字數 3888 閱讀 2657

#include #include #include #include enum majiangtype:uint8_t

;constexpr uint8_t mj(uint8_t m, uint8_t n)

inline majiangtype majiang_type(uint8_t m)

inline uint8_t majiang_value(uint8_t m)

enum emmj:uint8_t

;const std::setall_majiang_types = ;

//十三么牌型:13張再加其中任意一張

static const std::setpattern131 = ;

using majiangpai = std::vector;

template static t find_in_sorted(t begin, t end, v v)

else if (*it > v)

++it;

} return it;

}//遞迴拆分手牌

bool resolvepai(majiangpai pai, uint8_t joker_count)

else if (pai.size() + joker_count < 3)

if (pai.size() >= 3 && pai[0] == pai[2]) }

else if (pai.size() >= 2 && pai[0] == pai[1] && joker_count >= 1) }

else if (pai.size() >= 1 && joker_count >= 2) }

if (majiang_type(pai[0]) < emmjtype_zi)

else if(joker_count >= 1)

}else if(joker_count >= 1)

else if (joker_count >= 2)

}} return false;

}//普通和牌型別

bool iscommonhu(const majiangpai& original_pai)

pai = original_pai;

if (jiang_location != 0)

}//尋找將牌位置,記錄將牌第二個,並擦除該兩牌

jiang_location = 0;

for (; i < pai.size(); ++ i)

else if (pai[i] != emmj_joker && pai[0] == emmj_joker)

}if (jiang_location == 0)

//無賴子時可直接迴圈拆分,有賴子時較複雜一些,需要遞迴拆分

auto joker_end = pai.begin();

while (joker_end != pai.end() && *joker_end == emmj_joker)

uint8_t joker_count = joker_end - pai.begin();

if (joker_count > 0)

}else

else if (majiang_type(pai[0]) < emmjtype_zi)

else

}else

}else

}if (pai.empty())

}} return true;

}std::setis131ting(const majiangpai& original_pai)

auto pai_begin = original_pai.begin();

while (pai_begin != original_pai.end() && *pai_begin == emmj_joker)

uint8_t joker_count = pai_begin - original_pai.begin();

//先找將牌

auto it_jiang = pai_begin + 1;

while (it_jiang != original_pai.end())

++it_jiang;

} if (it_jiang == original_pai.end())

--joker_count;

++it2;

continue;

}++it1;

++it2;

} for (const auto& ting : pattern131)

return settingpai;

} //找到將牌,則如果是十三么就只能賴子個數加一張

auto pai = original_pai;

pai.erase(pai.begin() + (it_jiang - original_pai.begin()));

auto it1 = pai.cbegin() + joker_count;

auto it2 = pattern131.cbegin();

while(it1 != pai.cend() && it2 != pattern131.cend())

settingpai.insert(*it2);

++it2;

continue;

} ++it1;

++it2;

} if (it1 == pai.cend() && it2 != pattern131.cend())

return settingpai;

}std::setis7pairsting(const majiangpai& original_pai)

uint8_t joker_count = pai_begin - original_pai.begin();

for (; pai_begin != original_pai.end(); ++pai_begin)

else if(settingpai.size() > joker_count)

else

}if (pai_begin == original_pai.end() && settingpai.size() < joker_count)

}return settingpai;

}std::setcheckting(const majiangpai& pai)

ting_pai = is7pairsting(pai);

//小七對牌型與普通牌型相容,即可能和小七對,也可能普通和。

} //賴子個數:賴子牌編碼最小,在排好序的佇列前面

auto joker_end = pai.cbegin();

while (joker_end != pai.cend() && *joker_end == emmj_joker)

uint8_t jocker_count = joker_end - pai.cbegin();

for (auto i : all_majiang_types)

if (majiang_type(i) >= emmjtype_zi)

}else

);if (it == pai.cend())

}}

auto temp(pai);

auto range = std::equal_range(temp.begin(), temp.end(), i);

if (std::distance(range.first, range.second) == 4)

temp.insert(range.second, i);

if (iscommonhu(temp))

}return ting_pai;

}int main()

; auto ting = checkting(v);

for(auto i : ting)

return 0;

}

鬥地主含賴子的牌型判斷演算法

打出n張牌 可能含有賴子 需要判斷這n張牌能組成什麼牌型 對子 順子 飛機 整體思路 假設我們已經提前那種牌作為癩子。1 找出n張牌中的賴子,假設有m個賴子 2 計算出這剩餘n m張牌的牌值,存到和牌值一一對應的陣列,並記錄對應數量。3 計算剩餘牌能組成對應牌型所需要的賴子是否滿足需要。定義撲克陣列...

5180 帶限制的子串行和

可以利用雙向佇列進行視窗滑動 狀態方程 dp i 定義為 包含i的前i個數構成最大和 當然是滿足下標條件的最大和 dp i max dp i dp i j nums i j取值0 k 在這裡,每次回去尋找前面k個數中,哪個數構成和最大。迴圈過程中,前一次迴圈和本次的前k個數有k 1個數是相同的,利用...

LeetCode 5180 帶限制的子串行和

使用動態規劃,dp i 表示以i結束的最大子串行和,每個以i位置結束的有k 1個選擇,子串行只有這個元素或者從前面k個位置的某乙個位置接上。然後快速求前面k個的最大值,可以用到堆,從舊到新 從大到小佇列 struct node bool operator const node a,const nod...