红中癞子麻将胡牌算法中,何谓打甩牌

红中赖子杠这个怎么胡的求解癞子麻将胡牌算法实现
时间: 13:05:04
&&&& 阅读:430
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&最先实现的就是算法的实现。
需求:碰杠胡& ,不能吃 ,不能听 ,只能自摸胡,其中癞子可以做任意牌但是不能碰和杠。
写的时候还不会玩麻将,还是老板教的。^_^
最麻烦的是胡牌算法。之前搜到的都是不包含癞子正常的胡牌,用的是%3余2,其中余数2就是余的将的意思。
但是有癞子就不能这么用了。只好自己写一个了。
一个有136张牌,万,饼,条,东西南北中发白34种牌。
有四个癞子是直接就胡牌的,最坏的情况是有3个癞子,但是如果遍历一遍不用逻辑判断就有34X34X34接近4万次.
想一下如果能胡牌,最坏的情况下是在最后一次判断能胡牌,那之前的近4万次的判断都是浪费的。
这里转变一下思维,就是有目的的按需所取成胡牌所需要的癞子个数,而不是盲目遍历再判断胡牌。
算法的正确性:如果想胡牌必然是三扑一将(正常胡牌)。其中扑指的是顺子或者三重牌(比如 一饼二饼三饼)。将指的是两个重牌。
四种情况:
&&&&&&&&&&&&&&&&&&&&&&&& 1.假如将在【万】里面那么【饼】【条】【风】(包含中发白)必然是整扑。
&&&&&&&&&&&&&&&&&&&&&&&& 2.假如将在【饼】里面那么【万】【条】【风】(包含中发白)必然是整扑。
&&&&&&&&&&&&&&&&&&&&&&&& 3.假如将在【条】里面那么【万】【饼】【风】(包含中发白)必然是整扑。&&&&&&&&&&&&&&&&&&&&&&
& & & & & & & & & & & && 4.假如将在【风】里面(包含中发白)那么【万】【饼】【条】必然是整扑。
假如当前癞子的数目是curHunNum。
现在先获取【万】【饼】【条】【风】各自成为整扑所需要癞子的个数,如果是情况一。
needHunNum= 【饼】需要癞子的个数+【条】需要癞子的个数+【风】需要癞子的个数;
如果hadHunNum = needHunNum - curHunNum; 如果hadHunNum&0 需求的比拥有的多& 就不做判断。
否则就判断【万】中成为整扑一将需要的数目。
情况二三四依次类推。
主要有三个函数:
1.测试胡牌
bool Player::testHuPai(Pai* pai)
for (int i = MJPAI_HUN; i &= MJPAI_FENGZFB; i++)
myPaiCopy[i].clear();
vector&Pai*&::
for (int i = MJPAI_HUN; i &= MJPAI_FENGZFB; i++)
for (iter = m_MyPAIVec[i].begin(); iter != m_MyPAIVec[i].end(); iter++)
myPaiCopy[i].push_back(*iter);
insertPai(pai, myPaiCopy);
int curHunNum = myPaiCopy[MJPAI_HUN].size();
if (curHunNum&3)
CCLOG(&Four Hun!!&);
addIDEveryPai(myPaiCopy);
int needHunNum = 0;
int jiangNeedNum = 0;
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(myPaiCopy[MJPAI_WAN], 0);
int wanToPuNeedNum = needMinHunN
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(myPaiCopy[MJPAI_BING], 0);
int bingToPuNeedNum = needMinHunN
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(myPaiCopy[MJPAI_TIAO], 0);
int tiaoToPuNeedNum = needMinHunN
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(myPaiCopy[MJPAI_FENGZFB], 0);
int fengToPuNeedNum = needMinHunN
CCLOG(&wanToPuNeedNum:%d bingToPuNeedNum:%d tiaoToPuNeedNum:%d fengToPuNeedNum:%d&,
wanToPuNeedNum, bingToPuNeedNum, tiaoToPuNeedNum, fengToPuNeedNum);
//将在万中
//如果需要的混小于等于当前的则计算将在将在万中需要的混的个数
needHunNum = bingToPuNeedNum + tiaoToPuNeedNum + fengToPuNeedN
if (needHunNum &= curHunNum)
CCLOG(&jiang in wan:%d %d&, needHunNum, curHunNum);
int vecSize = myPaiCopy[MJPAI_WAN].size();
int hasNum = curHunNum - needHunN
m_HuPaiVec.clear();
//不装混牌
for (iter = myPaiCopy[MJPAI_WAN].begin(); iter != myPaiCopy[MJPAI_WAN].end(); iter++)
m_HuPaiVec.push_back(*iter);
bool isHu = vecCanHu(hasNum);
//将在饼中
needHunNum = wanToPuNeedNum + tiaoToPuNeedNum + fengToPuNeedN
if (needHunNum &= curHunNum)
CCLOG(&jiang in bing:%d %d&, needHunNum, curHunNum);
int vecSize = myPaiCopy[MJPAI_BING].size();
int hasNum = curHunNum - needHunN
m_HuPaiVec.clear();
//不装混牌
for (iter = myPaiCopy[MJPAI_BING].begin(); iter != myPaiCopy[MJPAI_BING].end(); iter++)
m_HuPaiVec.push_back(*iter);
bool isHu = vecCanHu(hasNum);
//将在条中
needHunNum = wanToPuNeedNum + bingToPuNeedNum + fengToPuNeedN
if (needHunNum &= curHunNum)
CCLOG(&jiang in tiao:%d %d&, needHunNum, curHunNum);
int vecSize = myPaiCopy[MJPAI_TIAO].size();
int hasNum = curHunNum - needHunN
m_HuPaiVec.clear();
//不装混牌
for (iter = myPaiCopy[MJPAI_TIAO].begin(); iter != myPaiCopy[MJPAI_TIAO].end(); iter++)
m_HuPaiVec.push_back(*iter);
bool isHu = vecCanHu(hasNum);
//将在风中
needHunNum = wanToPuNeedNum + bingToPuNeedNum + tiaoToPuNeedN
if (needHunNum &= curHunNum)
CCLOG(&jiang in feng:%d %d&, needHunNum, curHunNum);
int vecSize = myPaiCopy[MJPAI_FENGZFB].size();
int hasNum = curHunNum - needHunN
m_HuPaiVec.clear();
//不装混(癞子)牌
for (iter = myPaiCopy[MJPAI_FENGZFB].begin(); iter != myPaiCopy[MJPAI_FENGZFB].end(); iter++)
m_HuPaiVec.push_back(*iter);
bool isHu = vecCanHu(hasNum);
}2.成为整扑需要的癞子个数:
void Player::getNeedHunNumToBePu(vector&Pai*&typeVec, int needNum)
if (needMinHunNum == 0)
if (needNum &= needMinHunNum)
int vSize = typeVec.size();
if (vSize == 0)
needMinHunNum = MIN(needNum, needMinHunNum);
else if (vSize == 1)
needMinHunNum = MIN(needNum + 2, needMinHunNum);
else if (vSize == 2)
Pai* p1 = typeVec.at(0);
Pai* p2 = typeVec.at(1);
//如果后一个是东西南北中发白
不可能是出现顺牌
if (p2-&getType() == MJPAI_FENGZFB)
if (p1-&getValue() == p2-&getValue())
needMinHunNum = MIN(needMinHunNum, needNum + 1);
vector&Pai*&::
for (iter = typeVec.begin(); iter != typeVec.end(); iter++)
CCLOG(&3Pai:%d:Type:%d Value:%d&, needMinHunNum, (*iter)-&getType(), (*iter)-&getValue());
else if (p2-&getValue() - p1-&getValue() & 3)
needMinHunNum = MIN(needMinHunNum, needNum + 1);
//大于等于3张牌
Pai* p1 = typeVec.at(0);
Pai* p2 = typeVec.at(1);
Pai* p3 = typeVec.at(2);
//第一个自己一扑
if (needNum + 2&needMinHunNum)
typeVec = removeVector(p1, typeVec);
getNeedHunNumToBePu(typeVec, needNum + 2);
typeVec = insertVector(p1, typeVec);
//第一个跟其它的一个一扑
if (needNum + 1&needMinHunNum)
if (p1-&getType() == MJPAI_FENGZFB)
if (p1-&getValue() == p2-&getValue())
typeVec = removeVector(p1, typeVec);
typeVec = removeVector(p2, typeVec);
getNeedHunNumToBePu(typeVec, needNum + 1);
typeVec = insertVector(p2, typeVec);
typeVec = insertVector(p1, typeVec);
for (unsigned int i = 1; i & typeVec.size(); i++)
if (needNum + 1 &= needMinHunNum)
p2 = typeVec[i];
//455567这里可结合的可能为 45 46 否则是45 45 45 46
//如果当前的value不等于下一个value则和下一个结合避免重复
if (i + 1 != typeVec.size())
p3 = typeVec[i + 1];
if (p3-&getValue() == p2-&getValue());
if (p2-&getValue() - p1-&getValue() & 3)
typeVec = removeVector(p1, typeVec);
typeVec = removeVector(p2, typeVec);
getNeedHunNumToBePu(typeVec, needNum + 1);
typeVec = insertVector(p2, typeVec);
typeVec = insertVector(p1, typeVec);
//第一个和其它两个一扑
//后面间隔两张张不跟前面一张相同222234
//可能性为222 234
for (unsigned int i = 1; i & typeVec.size(); i++)
if (needNum &= needMinHunNum)
p2 = typeVec[i];
if (i + 2 & typeVec.size())
if (typeVec[i + 2]-&getValue() == p2-&getValue())
for (unsigned int j = i + 1; j & typeVec.size(); j++)
if (needNum &= needMinHunNum)
p3 = typeVec[j];
if (p1 == p3)
CCLOG(&cao!!&);
if (j + 1 & typeVec.size())
if (p3-&getValue() == typeVec[j + 1]-&getValue())
if (test3Combine(p1, p2, p3))
typeVec = removeVector(p1, typeVec);
typeVec = removeVector(p2, typeVec);
typeVec = removeVector(p3, typeVec);
getNeedHunNumToBePu(typeVec, needNum);
typeVec = insertVector(p3, typeVec);
typeVec = insertVector(p2, typeVec);
typeVec = insertVector(p1, typeVec);
}3.判断某一类型能否成为整扑一将:
bool Player::vecCanHu(int hunNum)
CCLOG(&vecCanHu&);
int huSize = m_HuPaiVec.size();
DebugPlayer(HUVEC);
if (huSize &= 0)
if (hunNum &= 2)
Pai* firstPai = m_HuPaiVec.front();
int kType = firstPai-&getType();
vector&Pai*&::
vector&Pai*& huPaiC
for (iter = m_HuPaiVec.begin(); iter != m_HuPaiVec.end(); iter++) huPaiCopy.push_back(*iter);
for (iter = huPaiCopy.begin(); iter != huPaiCopy.end(); iter++)
if (iter == huPaiCopy.end() - 1)
CCLOG(&last iterator!!&);
if (hunNum & 0)
hunNum = hunNum - 1;
removeHuPai(*iter);
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(m_HuPaiVec, 0);
if (needMinHunNum &= hunNum)
CCLOG(&T:%d V:%d&, (*iter)-&getType(), (*iter)-&getValue());
hunNum = hunNum + 1;
insertHuPai(*iter);
if ((iter + 2 == huPaiCopy.end()) || ((*iter)-&getValue() != (*(iter + 2))-&getValue()))
CCLOG(&other iterator!!&);
if (test2Combine(*iter, *(iter + 1)))
CCLOG(&%d %d&, (*iter)-&getType(), (*iter)-&getValue());
removeHuPai(*iter);
removeHuPai(*(iter + 1));
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(m_HuPaiVec, 0);
if (needMinHunNum &= hunNum)
CCLOG(&T:%d V:%d&, (*iter)-&getType(), (*iter)-&getValue());
insertHuPai(*iter);
insertHuPai(*(iter + 1));
if (hunNum&0 && (*iter)-&getValue() != (*(iter + 1))-&getValue())
CCLOG(&%d %d&, (*iter)-&getType(), (*iter)-&getValue());
hunNum = hunNum - 1;
removeHuPai(*iter);
needMinHunNum = MJPAI_HUNMAX;
getNeedHunNumToBePu(m_HuPaiVec, 0);
if (needMinHunNum &= hunNum)
CCLOG(&T:%d V:%d&, (*iter)-&getType(), (*iter)-&getValue());
hunNum = hunNum + 1;
insertHuPai(*iter);
}其中vecCanHu函数是可以再加强剪枝的比如改变癞子时候加上%3余2的思想。
麻将是快写完了,学到不少东西。加油吧,骚年!!
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&原文:http://blog.csdn.net/skillart/article/details/
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!

我要回帖

更多关于 癞子麻将胡牌算法java 的文章

 

随机推荐