文章目录
0 背景
因为项目需要,于是使用Qt编写了一个麻将软件。但是后面由于种种原因,软件被弃用了【当时就写了一个月,还是刚学完Qt写的,写的比较粗糙😂】,于是现在把项目开源,供大家参考交流、学习。
1 软件图片
1.1 设置
感觉这应该是市面上玩法最多的设置了,不过由于时间原因只实现了一小部分的功能,
1.2 游戏界面
- 抓庄
- 选庄,抽牌,【右上角显示庄家】
- 打牌过程,
1.3 识别界面
2 核心算法
2.1 牌类
牌类
class Mj;
class Mj {
// friend HuPaiKit;
public:
bool isHu() const{return hu;}
void setHu(bool hu) {this->hu = hu;}
bool isLast() const {return last;}
void setLast(bool last) {this->last = last;}
// ImageView getHupai_imageView() {return hupai_imageView;}
///缺一门(有用)
bool getIsque() const {return isque;}
void setIsque(bool isque) {this->isque = isque;}
//void setHupai_imageView(ImageView hupai_imageView) {this->hupai_imageView = hupai_imageView;}
///吃碰杠胡(有用)
int getPaizhuangtai() const {return paizhuangtai;}
void setPaizhuangtai(int paizhuangtai) {this->paizhuangtai = paizhuangtai;}
int getYuce_direction() {return yuce_direction;}
void setYuce_direction(int yuce_direction) {this->yuce_direction = yuce_direction;}
int getNapai_direction() {return napai_direction;}
void setNapai_direction(int napai_direction) {this->napai_direction = napai_direction;}
bool getSimo() {return simo;}
void setSimo(bool simo) {this->simo = simo;}
int getChupai_direction() {return chupai_direction;}
void setChupai_direction(int chupai_direction) {this->chupai_direction = chupai_direction;}
//Node getOther() {return other;}
//void setOther(Node other) {this->other = other;}
//ImageView getWeina_imageView() {return weina_imageView;}
//void setWeina_imageView(ImageView weina_imageView) {this->weina_imageView = weina_imageView;}
//MjControlInterface getYina_imageView() {return yina_imageView;}
//void setYina_imageView(MjControlInterface yina_imageView) {this->yina_imageView = yina_imageView;}
//MjControlInterface getYuce_imageView() {return yuce_imageView;}
//void setYuce_imageView(MjControlInterface yuce_imageView) {this->yuce_imageView = yuce_imageView;}
//ImageView getYichu_imageView() {return yichu_imageView;}
//void setYichu_imageView(ImageView yichu_imageView) {this->yichu_imageView = yichu_imageView;}
int getResult() const{return result;}
void setResult(int result) {this->result = result;}
//牌id(有用)
int getId() const {return id;}
void setId(int id) {this->id = id;}
int getSerial_number() {return serial_number;}
void setSerial_number(int serial_number) {this->serial_number = serial_number;}
int getMahjong_number() {return mahjong_number;}
void setMahjong_number(int mahjong_number) {this->mahjong_number = mahjong_number;}
int getDirection() {return direction;}
void setDirection(int direction) {this->direction = direction;}
int getZhuo_id() {return zhuo_id;}
void setZhuo_id(int zhuo_id) {this->zhuo_id = zhuo_id;}
bool isMaima() {return maima;}
void setMaima(bool maima) {this->maima = maima;}
std::string getZhiBiaoZHi() {return std::to_string(result) + "_" + std::to_string(yuanpai) ; }
///自写
bool isCaisheng() const{ return caisheng;}
bool operator==(const Mj mj) const {
if(this->result == mj.getResult()){
return true;
}else{
return false;
}
}
Mj& operator=(const Mj &mj) {
if(&mj != this){//自我赋值判断
result = mj.getResult();
paizhuangtai = mj.getPaizhuangtai();
id = mj.getId();
hu = mj.isHu() ;
last = mj.isLast();
isque = mj.getIsque();
}
return *this;
}
private:
int id;//id
int serial_number;//设备序列号 桌号
int mahjong_number;//第几张牌
int zhuo_id = 0;//局id
int direction;//设备方向
int napai_direction = -1;//拿牌方向
int yuce_direction = -1;//预测方向
int chupai_direction = -1;//出牌方向
std::string add_time;//时间
int result = -1;
int paizhuangtai = 0;//牌的状态 0:正常 1:碰 2:明杠 3:暗杠 4:吃的牌 5:胡牌
bool isque = false;//缺一门
bool simo = false;//是否已拿
bool maima = false;//买马
bool last = false;//最后摸的
bool hu = false;//胡的
public:
bool caisheng = false;//财神
int caisheng_dipai = 0;//财神所抵的牌
bool kedi_caisheng = false;//可抵财神
int yuanpai = 0;//抵财神或花牌的原牌
bool kedi_huapai = false;//可抵花牌
bool huapai_yuce = false;//预测花牌 杠后预测的牌
//private ImageView weina_imageView;
//private MjControlInterface yina_imageView;
//private MjControlInterface yuce_imageView;
//private ImageView yichu_imageView;
//private ImageView hupai_imageView;
//private Node other;
};
class Config;
class SystemConfig{
friend Config;
public:
//规则参数
int mapaicengshu=2;//码牌层数
int mapaifangshi=0;//码牌方式 0:摆两层 1:摆三层 2:单张(栋)在后 3:逐层码牌 4:136三层 5:144三层 6:摆四层(头+尾=六栋)
int wanjiapaishu=13;//玩家牌数
QString tiaopai="隔跳";//跳牌
int meishouzhangshu=4;//每手张数
int yucepai = 10;//预测牌
int wanjiarenshu=4;//玩家人数
int huanshoupai=0;//换手牌
int guoshanchediaohuan=0;//过山车调换牌
int zhuapaihouxuanzhuang=0;//抓牌后选庄
int sanceng_liangdongsizhang=0;//三层,两栋四张(抓牌)
int errenzhuaerfangweipai=0;//二人抓二方位牌
int qutouzhang=0;//去头张
int xianzhuan8houzhuan4=0;//先抓8后抓4
int meijuchongxuanquefang=0;//每局重选缺方
int disancengzuowanjiapai=0;//第三层做玩家牌
int meijushetiaopai=0;//每局设挑牌
int bugoudongyizhiweibu=0;//不够栋移至尾部
int _20zhangzhuangjiaxianzhuangsanzhangzaizhuayizhang=0;//20张庄家先抓3张再抓1张
int butiaopaizhangjialianxu14xian13=0;//不跳牌,庄家连续14,闲13
int zhuapai123=0;//抓牌123
int zhuapai321=0;//抓牌321
int pingna=0;//平拿
int niezhuanimo=0;//逆抓逆摸
int nanbeihuhuandongdexiajiashibei=0;//南北互换,东的下家是北
int zijiazuosandunyousandun=0;//自家左3墩右3墩
int sicengsandun=0;//四层3墩
int qishourenyiliangdong=0;//起手任意两栋
int renyiandongnapai=0;//任意按栋拿牌
//花牌
std::string gangfa="轮到自由杠(手动杠花)";//杠法
int zixuanhuapai=0;//自选花牌(非花牌当花)
int anhuiganghua=0;//安徽杠花(首轮)
int shoupaibuxianshihuapai=0;//手牌不显示花牌
int yucepaibuxianshihuapai=0;//预测牌不显示花牌
int anqingmajiangdahua=0;//安庆麻将打花
int huapaikepang_foushanmajiang=0;//花牌可碰(佛山麻将)
int huapaidaiticaishengpai_foushanmajiang=0;//花牌代替财神牌(佛山麻将140)
std::string ganghua="顺杠牌";//杠花
//扣牌
int diyishou=0;//第一手
int diershou=0;//第二手
int disanshou=0;//第三手
int zuihouyizhang=0;//最后一张
int zixuankoupai=1;//自选扣牌
//其它
int jiemianbuju=0;//界面布局
// double[] zidingyibeijingyanse={0,0,0};//自定义背景颜色
int shengyingtishi=0;//声音提示
int chupaixianshi=0;//出牌显示 0:出牌顺序 1;花色
int zidongjietu=0;//自动截图
int mimabaohu=0;//密码保护
int jianpancaozuomoshi=0;//键盘操作模式
int zhuomianbuxuanzhuan=0;//桌面牌不旋转
//打牌
int pongpai = 1;//碰牌(yong)
int chipai = 0;//吃牌(yong)
int baoliupai = 0;//保留手上的牌
int danzhangkechi = 0;//单张可吃
int chisanfangpai = 0;//吃三方牌
int gangshouzhongpai = 1;//杠手中牌(yong)
int fengpaizipaisanzhangkegang = 0;//风牌字牌三张可杠
int angang = 1;//暗杠(yong)
int minggang = 1;//明杠(yong)
int danzhangkegang = 0;//单张可杠
std::list<int> danzhangkegang_pai;//单张可杠的牌
int koupai=0;//扣牌(右击)
int dongnanxibeikechikegang=0;//东南西北可吃可杠
int zipaifengkai=0;//字牌分开(西南北,中发白)
int renyisangedanzhangzipai=0;//任意三个单张字牌
int leqing=0;//乐清(红中当花)
int dongnanxibeizhongfabaigang=0;//东南西北(中发白)杠
int dongnanxibeizhongfabaigangqingdao=0;//东南西北(中发白)杠(青岛)
int dongnanxibeizhongfabaishunzi=0;//东南西北(中发白)顺子
int pangjiang=0;//碰将
int yaojiyitongdangfengpai=0;//幺鸡一筒当风牌(甘肃)
int rengyijiu=0;//扔一九(甘肃)
int yaojiyitongdangzipai=0;//幺鸡一筒当字牌(甘肃)
int yaojiyitongdangzipaifengpai=0;//幺鸡一筒当字牌风牌(甘肃)
int wugezipaigang=0;//五个字牌杠(三个风牌两个箭牌,补两个)
int yaojiugangsangebubusigebuyige=0;//幺九杠(三个不补,四个补一个)
int yaojiugang=0;//幺九杠
int yaojiugangshengyangbusangehuosige=0;//幺九杠(沈阳补三个或四个)
int zhucengnapai=0;//逐层拿牌
int niezhuapai=0;//逆抓牌
int yingchuanbufeng=0;//银川补风
std::string gangpaishunxu="顺杠牌";//杠牌顺序
//胡牌
int zhixianzimo=0;//只限自摸
int qiangganghu=1;//抢杠胡
int erwubajiang=0;//二五八将
int queyimen =0;//缺一门
int xueliuchenghe=0;//血流成河
int hupaikepang=0;//胡牌可碰
int hupaikegang=0;//胡牌可杠
int fangpaoxiajia=0;//放炮下家
int yipaoduoxiang=1;//一炮多响
int hupaikemo=0;//胡牌可摸
int buchibupangdapaitishi=0;//不吃不碰打牌提示
int lanpai=0;//烂牌
int xiaoqidui=1;//小七对
int bixuyou19zipaifengpairenyiyizhang=0;//19字牌风牌任意一张
int pengpaihuozhezhongfabaidui=0;//碰牌或者中发白对
//财神
int zixuancaisheng=0;//自选财神
int houcaisheng=0;//后财神
int shunmocaisheng=0;//顺摸财神
int renyicaisheng=0;//任意财神
int shengjicaisheng=0;//升级财神
int shuangcaisheng=0;//双财神
int shangcaisheng_combox=0;//双财神
int zhongjianpaizuohua=0;//中间牌做花
int shengjicaishengshihuapaijixu=0;//升级财神是花牌继续升
int daiticaishengpai=0;//代替财神牌
int daiticaishengpai_combox=0;//代替财神牌
int daitipaibaoliuyuanpaizuoyong=0;//代替牌保留原牌作用
int caishenganzhengchangpaichanyuchangpanggang=0;//财神按正常牌参与吃碰杠
int andaitipaixianshi=0;//按代替牌显示
int budaiticaishengzipai=0;//不代替财神字牌
int buhuahoumocaisheng=0;//补花后摸财神
int caishengcanyuchipanggang=0;//财神参与吃碰杠(起飞)
int caishengkedangang=0;//财神可单杠
int jiaohuanpai=0;//交换牌(与拿牌位置倒数第三栋第一张)
int fankaidcaishengpaidanghua=0;//翻开的财神牌当花
int fankaidcaishengpaifangzuihouweizhi=0;//翻开的财神牌放在最后位置
int fankaishihuapaijixufan=0;//翻开是花牌继续翻
int caishenganzhengchangpaicanyuchengpanggang=0;//财神按正常牌参与吃碰杠
int zhuapaihouxuancaisheng=0;//抓牌后选财神
int zipaifengpaifenkaishengji=0;//字牌风牌分开升级
int fankaidepaibuzuocaisheng=0;//翻开的牌不做财神
//int
//快捷方式
std::string huoqushuju;//获取数据
std::string guopai;//过牌
std::string xunhuanguopai;//循环过牌
std::string guodong;//过栋
std::string kanchupai;//看出牌
std::string mopai="空格键";//摸牌
std::string chipai_kjj;//吃牌
std::string gangpai;//杠牌
std::string pangpai_kjj;//碰牌
std::string chexiao="z";//撤销
std::string chongxuanzhuang;//重选庄
std::string shubiaoyouji="撤销";//鼠标右击
int leqingmajiang=0;//乐清麻将
int guangxi152=0;//广西152
int xianmajiang=0;//仙麻将
int yuhuanwahua=0;//玉环挖花
int wenchengmajiang=0;//文城麻将
int wenlingmajiang=0;//温岭麻将
int xianmaimahoudingzhuang=0;//先买马后定庄
};
class MjConfig {
public:
int getId() {return id;}
void setId(int id) {this->id = id;}
int getNumber() { return number;}
void setNumber(int number) {this->number = number;}
std::string getName() {return name;}
void setName(std::string name) {this->name = name;}
std::string getUrl() {return url;}
void setUrl(std::string url) {this->url = url;}
private:
int id;
int number;
std::string name;
std::string url;
};
2.2 胡牌
思想:先移除顺子,再移除刻子,最后判断将。
//正式版
bool UIMainWindows::HuPaiPanDin(std::list<Mj> mahs, int que, SystemConfig systemConfig)
{
//缺一门
if (systemConfig.queyimen == 1) {
for (Mj mj : mahs) {
if (mj.getIsque() == true && mj.isCaisheng() == false) {
return false;
}
}
}
list<Mj> pais = mahs;
//先剔除碰 杠的牌
list<Mj>::iterator iterator = pais.begin();
while (iterator != pais.end()) {
if (iterator->getPaizhuangtai() == 1 || iterator->getPaizhuangtai() == 2 || iterator->getPaizhuangtai() == 3 || iterator->getPaizhuangtai() == 4) {
iterator = pais.erase(iterator);
}else{
iterator++;
}
}
if (pais.size() % 3 != 2) {
return false;
}
//qDebug()<<"HuPaiPanDin 1";
bool kehu = hupaipanduan(pais, systemConfig);
//qDebug()<<"HuPaiPanDin 2";
return kehu;
}
bool UIMainWindows::hupaipanduan(std::list<Mj> cards, SystemConfig systemConfig)
{
list<Mj> pais = cards;//复制一根备份
//统计每张牌出现的次数
unordered_map<int, int> Map;
for (list<Mj>::iterator i = pais.begin(); i != pais.end(); ++i) {
if (Map.find(i->getResult()) != Map.end()) {
Map[i->getResult()]++;
} else {
Map[i->getResult()] = 1;
}
}
//统计出现次数
list<int> result_count;//出现的次数
for (unordered_map<int,int>::const_iterator i = Map.begin(); i != Map.end(); ++i) {
result_count.push_back(i->second);
}
int cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;//出现1,2,3,4次
for (list<int>::iterator i = result_count.begin(); i != result_count.end(); ++i) {
if (*i == 1) {//出现一次的
cnt1++;
}
if (*i == 2) {//出现两次的
cnt2++;
}
if (*i == 3) {//出现三次的
cnt3++;
}
if (*i == 4) {//出现四次的
cnt4++;
}
}
//所有的牌全部都能组成2个 胡牌
if (cnt2 * 2 == systemConfig.wanjiapaishu + 1) {//小七对
return true;
}
//只有两张牌
if (pais.size() == 2) {//刚好凑成将
return pais.begin()->getResult() == (++pais.begin())->getResult();
}
//有至少两个4张一样的牌,其余牌都是对子 胡牌(龙七对)
if (cnt4 > 1 && (cnt2 * 2 + cnt4 * 4 == static_cast<int>(pais.size()))) {
return true;
}
//有4张一样的牌且没杠,其余牌都是对子 (小七对)
if(cnt2 == 5 && cnt4 == 1){
return true;
}
//d都是四个加一对 胡牌(18罗汉)
if (cnt2 == 1 && cnt4 * 4 == static_cast<int>(pais.size()) - 2) {
return true;
}
if(systemConfig.erwubajiang == 1){
//全部是3个相同的加一对将
if(cnt2 == 1 && cnt3 * 3 == static_cast<int>(pais.size()) - 2){
for(auto i:Map){
if(i.second == 2){
if(i.first % 10 == 2 || i.first % 10 == 5 || i.first % 10 == 8){
return true;
}
}
}
}
for (unordered_map<int, int>::iterator sub_enty = Map.begin();sub_enty != Map.end();sub_enty++) {//至少有一个顺子的胡牌组合
list<Mj> suanpai = pais;//算牌(重置)
list<Mj> tempSuanpai;
list<Mj>::iterator iterator = suanpai.begin();
int jiangCnt = 0;
int testNum = sub_enty->first;//用于调试
while(iterator != suanpai.end()){
if(iterator->getResult() == sub_enty->first && jiangCnt < 2 && (sub_enty->first % 10 == 2 || sub_enty->first % 10 == 5 || sub_enty->first % 10 == 8)){
iterator = suanpai.erase(iterator);
jiangCnt++;
}else{
iterator++;
}
}
if(suanpai.size() % 3 != 0){//剩下的不是3的倍数
continue;
}
//排序
suanpai.sort(ComparatorMjResult2);
tempSuanpai = suanpai;
//先移除顺子再移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
//移除顺子
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(isSequence(suanpai,iterator->getResult()) == true){
//qDebug()<<"顺子前:"<<iterator->getResult();
int pai = iterator->getResult();
int nPai1 = pai + 1;
int nPai2 = pai + 2;
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai1){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai2){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == pai){
iterator = suanpai.erase(i);
break;
}
}
if(suanpai.size() > 0){
//qDebug()<<"顺子后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
// if(testNum == 1){
// qDebug()<<"调试";
// }
//移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(iterator->getResult() != sub_enty->first && isTriplet(suanpai, iterator->getResult()) == true){//删除刻字
//qDebug()<<"iterator刻字前:"<<iterator->getResult();
int pai = iterator->getResult();
int cnt = 0;
for(list<Mj>::iterator i = suanpai.begin();i != suanpai.end();){
if(pai == i->getResult()){
i = suanpai.erase(i);
cnt++;
}else{
i++;
}
if(cnt == 3){
break;
}
}
if(suanpai.size() > 0){
iterator = suanpai.begin();
//qDebug()<<"iterator刻字后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
if (suanpai.size() == 0) {
qDebug()<<"胡牌将:"<<testNum;
return true;
}
// if(testNum == 7){
// qDebug()<<"调试";
// }
suanpai = tempSuanpai;//有一对刻字,其余的都是顺子(刻字被拆未顺子)
iterator = suanpai.begin();
//移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
int getTriplet = 0;
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(getTriplet != 0){break;}
if(iterator->getResult() != sub_enty->first && isTriplet(suanpai, iterator->getResult()) == true){//删除刻字
//qDebug()<<"iterator刻字前:"<<iterator->getResult();
int pai = iterator->getResult();
int cnt = 0;
for(list<Mj>::iterator i = suanpai.begin();i != suanpai.end();){
if(pai == i->getResult()){
i = suanpai.erase(i);
cnt++;
getTriplet++;
}else{
i++;
}
if(cnt == 3){
break;
}
}
if(suanpai.size() > 0){
iterator = suanpai.begin();
// qDebug()<<"iterator刻字后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
//先移除顺子再移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
//移除顺子
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(isSequence(suanpai,iterator->getResult()) == true){
//qDebug()<<"顺子前:"<<iterator->getResult();
int pai = iterator->getResult();
int nPai1 = pai + 1;
int nPai2 = pai + 2;
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai1){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai2){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == pai){
iterator = suanpai.erase(i);
break;
}
}
if(suanpai.size() > 0){
// qDebug()<<"顺子后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
if (suanpai.size() == 0) {
qDebug()<<"胡牌将:"<<testNum;
return true;
}
}
}else{
//全部是3个相同的加一对将
if(cnt2 == 1 && cnt3 * 3 == static_cast<int>(pais.size()) - 2){
return true;
}
for (unordered_map<int, int>::iterator sub_enty = Map.begin();sub_enty != Map.end();sub_enty++) {//至少有一个顺子的胡牌组合
list<Mj> suanpai = pais;//算牌(重置)
list<Mj> tempSuanpai;
list<Mj>::iterator iterator = suanpai.begin();
int jiangCnt = 0;
int testNum = sub_enty->first;//用于调试
while(iterator != suanpai.end()){
if(iterator->getResult() == sub_enty->first && jiangCnt < 2){
iterator = suanpai.erase(iterator);
jiangCnt++;
}else{
iterator++;
}
}
if(suanpai.size() % 3 != 0){//剩下的不是3的倍数
continue;
}
//排序
suanpai.sort(ComparatorMjResult2);
tempSuanpai = suanpai;
//先移除顺子再移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
//移除顺子
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(isSequence(suanpai,iterator->getResult()) == true){
//qDebug()<<"顺子前:"<<iterator->getResult();
int pai = iterator->getResult();
int nPai1 = pai + 1;
int nPai2 = pai + 2;
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai1){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai2){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == pai){
iterator = suanpai.erase(i);
break;
}
}
if(suanpai.size() > 0){
//qDebug()<<"顺子后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
// if(testNum == 1){
// qDebug()<<"调试";
// }
//移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(iterator->getResult() != sub_enty->first && isTriplet(suanpai, iterator->getResult()) == true){//删除刻字
//qDebug()<<"iterator刻字前:"<<iterator->getResult();
int pai = iterator->getResult();
int cnt = 0;
for(list<Mj>::iterator i = suanpai.begin();i != suanpai.end();){
if(pai == i->getResult()){
i = suanpai.erase(i);
cnt++;
}else{
i++;
}
if(cnt == 3){
break;
}
}
if(suanpai.size() > 0){
iterator = suanpai.begin();
// qDebug()<<"iterator刻字后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
if (suanpai.size() == 0) {
qDebug()<<"胡牌将:"<<testNum;
return true;
}
// if(testNum == 7){
// qDebug()<<"调试";
// }
suanpai = tempSuanpai;//有一对刻字,其余的都是顺子(刻字被拆未顺子)
iterator = suanpai.begin();
//移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
int getTriplet = 0;
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(getTriplet != 0){break;}
if(iterator->getResult() != sub_enty->first && isTriplet(suanpai, iterator->getResult()) == true){//删除刻字
qDebug()<<"iterator刻字前:"<<iterator->getResult();
int pai = iterator->getResult();
int cnt = 0;
for(list<Mj>::iterator i = suanpai.begin();i != suanpai.end();){
if(pai == i->getResult()){
i = suanpai.erase(i);
cnt++;
getTriplet++;
}else{
i++;
}
if(cnt == 3){
break;
}
}
if(suanpai.size() > 0){
iterator = suanpai.begin();
//qDebug()<<"iterator刻字后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
//先移除顺子再移除刻字
if(suanpai.size() > 0){
iterator = suanpai.begin();
}
//移除顺子
while(suanpai.size() > 0 && iterator != suanpai.end()){
if(isSequence(suanpai,iterator->getResult()) == true){
// qDebug()<<"顺子前:"<<iterator->getResult();
int pai = iterator->getResult();
int nPai1 = pai + 1;
int nPai2 = pai + 2;
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai1){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == nPai2){
suanpai.erase(i);
break;
}
}
for(list<Mj>::iterator i = suanpai.begin(); i!= suanpai.end();i++){
if(i->getResult() == pai){
iterator = suanpai.erase(i);
break;
}
}
if(suanpai.size() > 0){
// qDebug()<<"顺子后:"<<iterator->getResult();
}
}else{
iterator++;
}
}
if (suanpai.size() == 0) {
qDebug()<<"胡牌将:"<<testNum;
return true;
}
}
}
return false;
}
2.3 其他(明杠、暗杠、抢杠胡)
3 花絮
3.1 游戏
在计算排版
打牌状态图片测试:
测试选庄:
3.2 识别图片