网狐精华版麻将分析代码阅读记录

主要理解的点是 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);
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值