主要理解的点是 34 这个概念
把这个概念理解清楚了 其实也就明白这套算法了
今天看这段代码记录下,
改吃胡判断前,先看到这段代码,吃胡会用到这个方法产生的
CAnalyseItemArray & AnalyseItemArray
所以需要先把这个数组搞清楚是什么东西才行,此数组key value 均为:
//分析子项
struct tagAnalyseItem
{
BYTE cbCardEye; //牌眼扑克
bool bMagicEye; //牌眼是否是王霸
BYTE cbWeaveKind[MAX_WEAVE]; //组合类型
BYTE cbCenterCard[MAX_WEAVE]; //中心扑克
BYTE cbCardData[MAX_WEAVE][4]; //实际扑克
};
其实看不明白到底是干嘛的,但是 在分析扑克方法中,可以先搞清楚在哪儿给这个数组赋值
手牌数量用此公式计算出来的结果
如果是0 ,单吊
如果大于等于3那就拆分俩布走,一个是连牌判断 一个是同牌判断
连牌的话 就是 123 234 345 等等,
同牌的话就是 111(刻) 或者 1111(杠)
连牌和同牌都会做一个tagAnalyseItem结构体 然后添加到 AnalyseItemArray中去
俩者区别是
TempKindItem.cbWeaveKind=WIK_PENG;//碰牌类型
TempKindItem.cbWeaveKind=WIK_LEFT;//左吃类型
把代码贴出来吧,加上我的注解
用此方法分析完扑克后,会遍历出手中的牌的组合,然后处理吃胡
//分析扑克
bool CGameLogic::AnalyseCard(const BYTE cbCardIndex1[MAX_INDEX], const tagWeaveItem WeaveItem[], BYTE cbWeaveCount, CAnalyseItemArray & AnalyseItemArray)
{
//AnalyseItemArray 这个是分析麻将后的结果
//计算数目,获取到的值是手牌值,初始为14,如果你碰、吃牌后,此处会减去相应的牌数量
BYTE cbCardCount=GetCardCount(cbCardIndex1);
//效验数目,这个不用看逻辑,是校验大小相公的基础公式
ASSERT((cbCardCount>=2)&&(cbCardCount<=MAX_COUNT)&&((cbCardCount-2)%3==0));
if ((cbCardCount<2)||(cbCardCount>MAX_COUNT)||((cbCardCount-2)%3!=0))
return false;
BYTE cbCardIndex[MAX_INDEX]={0};
CopyMemory(cbCardIndex,cbCardIndex1,sizeof(cbCardIndex));
if(m_cbMagicIndex[1] != MAX_INDEX)//癞子处理,我的麻将没癞子,所以不用看这段逻辑直接略过,只要把癞子个数设置为0就好了
{
cbCardIndex[m_cbMagicIndex[0]] += cbCardIndex[m_cbMagicIndex[1]];
cbCardIndex[m_cbMagicIndex[1]]=0;
}
//变量定义
BYTE cbKindItemCount=0;
tagKindItem KindItem[27*2+28+16];
ZeroMemory(KindItem,sizeof(KindItem));
tagKindItem TempKindItem;
ZeroMemory(&TempKindItem,sizeof(TempKindItem));
bool bMagicThree=false;
//需求判断。根据手牌值,计算当前牌的状态
//胡牌万能公式为 M*AAA + N*ABC + Q*DD
//M、N、Q为系数,所以套用此公式得下述方法
BYTE cbLessKindItem=(cbCardCount-2)/3;
ASSERT((cbLessKindItem+cbWeaveCount)==MAX_WEAVE);
//单吊判断
if (cbLessKindItem==0)//(14-3*4)-2=0
{
//效验参数
ASSERT((cbCardCount==2)&&(cbWeaveCount==MAX_WEAVE));
//牌眼判断
for (BYTE i=0;i<MAX_INDEX;i++)
{
if (cbCardIndex[i]==2 || (m_cbMagicIndex[0] != MAX_INDEX && i != m_cbMagicIndex[0] && cbCardIndex[m_cbMagicIndex[0]]+cbCardIndex[i]==2))
{
//变量定义
tagAnalyseItem AnalyseItem;
ZeroMemory(&AnalyseItem,sizeof(AnalyseItem));
//设置结果
for (BYTE j=0;j<cbWeaveCount;j++)
{
AnalyseItem.cbWeaveKind[j]=WeaveItem[j].cbWeaveKind;
AnalyseItem.cbCenterCard[j]=WeaveItem[j].cbCenterCard;
CopyMemory(AnalyseItem.cbCardData[j],WeaveItem[j].cbCardData,sizeof(WeaveItem[j].cbCardData));
}
if(cbCardIndex[i] < 2 || i == m_cbMagicIndex[0])
AnalyseItem.bMagicEye = true;
else AnalyseItem.bMagicEye = false;
AnalyseItem.cbCardEye=cbCardIndex[i]==0?SwitchToCardData(cbCardIndex[m_cbMagicIndex[0]]):SwitchToCardData(i);
//插入结果
AnalyseItemArray.Add(AnalyseItem);
return true;
}
}
return false;
}
//拆分分析
BYTE cbMagicCardIndex[MAX_INDEX];
CopyMemory(cbMagicCardIndex,cbCardIndex,sizeof(cbMagicCardIndex));
//如果有财神
BYTE cbMagicCardCount = 0;
BYTE cbTempMagicCount = 0;
if(m_cbMagicIndex[0] != MAX_INDEX)
{
cbMagicCardCount = cbCardIndex[m_cbMagicIndex[0]];
//如果财神有代替牌,财神与代替牌转换
if(INDEX_REPLACE_CARD != MAX_INDEX)
{
cbMagicCardIndex[m_cbMagicIndex[0]] = cbMagicCardIndex[INDEX_REPLACE_CARD];
cbMagicCardIndex[INDEX_REPLACE_CARD] = cbMagicCardCount;
}
}
if (cbCardCount>=3)
{
for (BYTE i=0;i<MAX_INDEX-MAX_HUA_INDEX;i++)
{
//同牌判断
//如果是财神,并且财神数小于3,则不进行组合
if(cbMagicCardIndex[i] >= 3 || (cbMagicCardIndex[i]+cbMagicCardCount >= 3 &&
((INDEX_REPLACE_CARD!=MAX_INDEX && i != INDEX_REPLACE_CARD) || (INDEX_REPLACE_CARD==MAX_INDEX && i != m_cbMagicIndex[0])))
)
{
int nTempIndex = cbMagicCardIndex[i];
do
{
ASSERT(cbKindItemCount < CountArray(KindItem));
BYTE cbIndex = i;
BYTE cbCenterCard = SwitchToCardData(i);
//如果是财神且财神有代替牌,则换成代替牌
if(i == m_cbMagicIndex[0] && INDEX_REPLACE_CARD != MAX_INDEX)
{
cbIndex = INDEX_REPLACE_CARD;
cbCenterCard = SwitchToCardData(INDEX_REPLACE_CARD);
}
TempKindItem.cbWeaveKind=WIK_PENG;
TempKindItem.cbCenterCard=cbCenterCard;
TempKindItem.cbValidIndex[0] = nTempIndex>0?cbIndex:m_cbMagicIndex[0];
TempKindItem.cbValidIndex[1] = nTempIndex>1?cbIndex:m_cbMagicIndex[0];
TempKindItem.cbValidIndex[2] = nTempIndex>2?cbIndex:m_cbMagicIndex[0];
AddKindItem(TempKindItem, KindItem, cbKindItemCount, bMagicThree);
//当前索引牌未与财神组合 且财神个数不为0
if(nTempIndex>=3 && cbMagicCardCount >0)
{
--nTempIndex;
//1个财神与之组合
TempKindItem.cbWeaveKind=WIK_PENG;
TempKindItem.cbCenterCard=cbCenterCard;
TempKindItem.cbValidIndex[0] = nTempIndex>0?cbIndex:m_cbMagicIndex[0];
TempKindItem.cbValidIndex[1] = nTempIndex>1?cbIndex:m_cbMagicIndex[0];
TempKindItem.cbValidIndex[2] = nTempIndex>2?cbIndex:m_cbMagicIndex[0];
AddKindItem(TempKindItem, KindItem, cbKindItemCount, bMagicThree);
//两个财神与之组合
if(cbMagicCardCount>1)
{
TempKindItem.cbWeaveKind=WIK_PENG;
TempKindItem.cbCenterCard=cbCenterCard;
TempKindItem.cbValidIndex[0] = nTempIndex>0?cbIndex:m_cbMagicIndex[0];
TempKindItem.cbValidIndex[1] = nTempIndex>1?cbIndex:m_cbMagicIndex[0];
TempKindItem.cbValidIndex[2] = nTempIndex>2?cbIndex:m_cbMagicIndex[0];
AddKindItem(TempKindItem, KindItem, cbKindItemCount, bMagicThree);
}
++nTempIndex;
}
//如果是财神,则退出
if(i == INDEX_REPLACE_CARD || ((i == m_cbMagicIndex[0]) && INDEX_REPLACE_CARD == MAX_INDEX))
break;
nTempIndex -= 3;
//如果刚好搭配全部,则退出
if(nTempIndex == 0) break;
}while(nTempIndex+cbMagicCardCount >= 3);
}
//连牌判断
if ( ((i<(MAX_INDEX-MAX_HUA_INDEX-9))&&((i%9)<7)) || (G_ZI_SHUN && i==31) )
{
//只要财神牌数加上3个顺序索引的牌数大于等于3,则进行组合
if(cbMagicCardCount+cbMagicCardIndex[i]+cbMagicCardIndex[i+1]+cbMagicCardIndex[i+2] >= 3)
{
BYTE cbIndex[3] = { cbMagicCardIndex[i],cbMagicCardIndex[i+1],cbMagicCardIndex[i+2] };
if(cbIndex[0]+cbIndex[1]+cbIndex[2]==0) continue;
int nMagicCountTemp;
nMagicCountTemp = cbMagicCardCount;
BYTE cbValidIndex[3];
while(nMagicCountTemp+cbIndex[0]+cbIndex[1]+cbIndex[2] >= 3)
{
for(BYTE j = 0; j < CountArray(cbIndex); j++)
{
if(cbIndex[j] > 0)
{
cbIndex[j]--;
cbValidIndex[j] = ((i+j==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j;
}
else
{
nMagicCountTemp--;
cbValidIndex[j] = m_cbMagicIndex[0];
}
}
if(nMagicCountTemp >= 0)
{
ASSERT(cbKindItemCount < CountArray(KindItem));
TempKindItem.cbWeaveKind=WIK_LEFT;
TempKindItem.cbCenterCard=SwitchToCardData(i);
CopyMemory(TempKindItem.cbValidIndex,cbValidIndex,sizeof(cbValidIndex));
AddKindItem(TempKindItem, KindItem, cbKindItemCount, bMagicThree);
}
else break;
}
}
}
else if(G_ZI_SHUN && i==27)//东南西北任意三个可成顺
{
BYTE cbTempIndex[4][3]={0};
cbTempIndex[0][0]=cbMagicCardIndex[i];
cbTempIndex[0][1]=cbMagicCardIndex[i+1];
cbTempIndex[0][2]=cbMagicCardIndex[i+2];
cbTempIndex[1][0]=cbMagicCardIndex[i];
cbTempIndex[1][1]=cbMagicCardIndex[i+1];
cbTempIndex[1][2]=cbMagicCardIndex[i+3];
cbTempIndex[2][0]=cbMagicCardIndex[i];
cbTempIndex[2][1]=cbMagicCardIndex[i+2];
cbTempIndex[2][2]=cbMagicCardIndex[i+3];
cbTempIndex[3][0]=cbMagicCardIndex[i+1];
cbTempIndex[3][1]=cbMagicCardIndex[i+2];
cbTempIndex[3][2]=cbMagicCardIndex[i+3];
for(int index = 0;index<4;index++)
{
//只要财神牌数加上3个顺序索引的牌数大于等于3,则进行组合
if(cbMagicCardCount+cbTempIndex[index][0]+cbTempIndex[index][1]+cbTempIndex[index][2] >= 3)
{
BYTE cbIndex[3] = { cbTempIndex[index][0],cbTempIndex[index][1],cbTempIndex[index][2] };
if(cbIndex[0]+cbIndex[1]+cbIndex[2]==0) continue;
int nMagicCountTemp;
nMagicCountTemp = cbMagicCardCount;
BYTE cbValidIndex[3];
while(nMagicCountTemp+cbIndex[0]+cbIndex[1]+cbIndex[2] >= 3)
{
for(BYTE j = 0; j < CountArray(cbIndex); j++)
{
if(cbIndex[j] > 0)
{
cbIndex[j]--;
if(index==0)
cbValidIndex[j] = ((i+j==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j;
else if(index==1)
{
if(j==2)
cbValidIndex[j] = ((i+j+1==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j+1;
else
cbValidIndex[j] = ((i+j==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j;
}
else if(index==2)
{
if(j==0)
cbValidIndex[j] = ((i+j==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j;
else
cbValidIndex[j] = ((i+j+1==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j+1;
}
else if(index==3)
{
cbValidIndex[j] = ((i+j+1==m_cbMagicIndex[0]) && INDEX_REPLACE_CARD!=MAX_INDEX)?INDEX_REPLACE_CARD:i+j+1;
}
}
else
{
nMagicCountTemp--;
cbValidIndex[j] = m_cbMagicIndex[0];
}
}
if(nMagicCountTemp >= 0)
{
ASSERT(cbKindItemCount < CountArray(KindItem));
TempKindItem.cbWeaveKind=WIK_LEFT;
TempKindItem.cbCenterCard=SwitchToCardData(i);
CopyMemory(TempKindItem.cbValidIndex,cbValidIndex,sizeof(cbValidIndex));
AddKindItem(TempKindItem, KindItem, cbKindItemCount, bMagicThree);
}
else break;
}
}
}
}
}
}
//组合分析
if (cbKindItemCount>=cbLessKindItem)
{
ASSERT(27*2+28+16 >= cbKindItemCount);
//变量定义
BYTE cbCardIndexTemp[MAX_INDEX];
ZeroMemory(cbCardIndexTemp,sizeof(cbCardIndexTemp));
//变量定义
BYTE cbIndex[MAX_WEAVE];
for(BYTE i = 0; i < CountArray(cbIndex); i++)
cbIndex[i] = i;
tagKindItem * pKindItem[MAX_WEAVE];
ZeroMemory(&pKindItem,sizeof(pKindItem));
tagKindItem KindItemTemp[CountArray(KindItem)];
//开始组合
do
{
//如果四个组合中的混牌大于手上的混牌个数则重置索引
cbTempMagicCount = 0;
for(int i=0;i<cbLessKindItem;i++) cbTempMagicCount += KindItem[cbIndex[i]].cbMagicCount;
if(cbTempMagicCount <= cbMagicCardCount)
{
//设置变量
CopyMemory(cbCardIndexTemp,cbCardIndex,sizeof(cbCardIndexTemp));
CopyMemory(KindItemTemp,KindItem,sizeof(KindItem));
for (BYTE i=0;i<cbLessKindItem;i++)
pKindItem[i]=&KindItemTemp[cbIndex[i]];
//数量判断
bool bEnoughCard=true;
for (BYTE i=0;i<cbLessKindItem*3;i++)
{
//存在判断
BYTE cbCardIndex=pKindItem[i/3]->cbValidIndex[i%3];
if (cbCardIndexTemp[cbCardIndex]==0)
{
if(m_cbMagicIndex[0] != MAX_INDEX && cbCardIndexTemp[m_cbMagicIndex[0]] > 0)
{
pKindItem[i/3]->cbValidIndex[i%3] = m_cbMagicIndex[0];
cbCardIndexTemp[m_cbMagicIndex[0]]--;
}
else
{
bEnoughCard=false;
break;
}
}
else cbCardIndexTemp[cbCardIndex]--;
}
//胡牌判断
if (bEnoughCard==true)
{
//牌眼判断
BYTE cbCardEye=0;
bool bMagicEye = false;
if(GetCardCount(cbCardIndexTemp) == 2)
{
if(m_cbMagicIndex[0] != MAX_INDEX && cbCardIndexTemp[m_cbMagicIndex[0]]==2)
{
cbCardEye = SwitchToCardData(m_cbMagicIndex[0]);
bMagicEye = true;
}
else
{
for (BYTE i=0;i<MAX_INDEX;i++)
{
if (cbCardIndexTemp[i]==2)
{
cbCardEye=SwitchToCardData(i);
if(m_cbMagicIndex[0] != MAX_INDEX && i == m_cbMagicIndex[0])
{
bMagicEye = true;
}
break;
}
else if(i!=m_cbMagicIndex[0] && m_cbMagicIndex[0] != MAX_INDEX && cbCardIndexTemp[i]+cbCardIndexTemp[m_cbMagicIndex[0]]==2)
{
cbCardEye = SwitchToCardData(i);
bMagicEye = true;
break;
}
}
}
}
//组合类型
if (cbCardEye!=0)
{
//变量定义
tagAnalyseItem AnalyseItem;
ZeroMemory(&AnalyseItem,sizeof(AnalyseItem));
//设置组合
for (BYTE i=0;i<cbWeaveCount;i++)
{
AnalyseItem.cbWeaveKind[i]=WeaveItem[i].cbWeaveKind;
AnalyseItem.cbCenterCard[i]=WeaveItem[i].cbCenterCard;
GetWeaveCard(WeaveItem[i].cbWeaveKind,WeaveItem[i].cbCenterCard,AnalyseItem.cbCardData[i]);
}
//设置牌型
for (BYTE i=0;i<cbLessKindItem;i++)
{
AnalyseItem.cbWeaveKind[i+cbWeaveCount]=pKindItem[i]->cbWeaveKind;
AnalyseItem.cbCenterCard[i+cbWeaveCount]=pKindItem[i]->cbCenterCard;
AnalyseItem.cbCardData[cbWeaveCount+i][0] = SwitchToCardData(pKindItem[i]->cbValidIndex[0]);
AnalyseItem.cbCardData[cbWeaveCount+i][1] = SwitchToCardData(pKindItem[i]->cbValidIndex[1]);
AnalyseItem.cbCardData[cbWeaveCount+i][2] = SwitchToCardData(pKindItem[i]->cbValidIndex[2]);
}
//设置牌眼
AnalyseItem.cbCardEye=cbCardEye;
AnalyseItem.bMagicEye = bMagicEye;
//插入结果
AnalyseItemArray.Add(AnalyseItem);
}
}
}
//设置索引
if (cbIndex[cbLessKindItem-1]==(cbKindItemCount-1))
{
BYTE i = cbLessKindItem - 1;
for (;i>0;i--)
{
if ((cbIndex[i-1]+1)!=cbIndex[i])
{
BYTE cbNewIndex=cbIndex[i-1];
for (BYTE j=(i-1);j<cbLessKindItem;j++)
cbIndex[j]=cbNewIndex+j-i+2;
break;
}
}
if (i==0)
break;
}
else
cbIndex[cbLessKindItem-1]++;
} while (true);
}
return (AnalyseItemArray.GetCount()>0);
}