斗地主提示牌

斗地主提示牌

获取快速组合牌;
1、取王炸
2、取顺子组合
3、取炸弹飞机三张连对
4、给炸弹飞机三张配料如3带1,3
不过应该是不是先取连对特别的策略
//获取连对4455666 445566 6 44666 55
// 4455666 999 445566 6999 or 44666 55999 rule

	// 3个农民
	/// </summary>
	typedef enum
	{
		UserFarmer0,//农民
		UserFarmer1,//农民
		UserFarmer2,//农民
		UserPending,//待定
		UserMax
	}UserType;
	
	/// 卡牌花色
	/// </summary>
	typedef enum
	{
		Diamond,//方块
		Heart,//红桃
		Spade,//黑桃
		Club,//梅花
		Joker,//王
		ColorMax
	}ColorType;

	/// 卡牌的权值
	/// </summary>
	typedef enum 
	{
		Three,		// 3-9
		Four,
		Five,
		Six,
		Seven,
		Eight,
		Nine,
		Ten,
		Jack,		// J
		Queen,		// Q
		King,		// K
		One,		// A
		Two,		// 2
		SJoker, 	// 小王
		LJoker,		// 大王
		CardMax
	}CardType;
	
	/// <summary>
	/// 出牌类型
	/// </summary>
	typedef enum 
	{
		None,
		Single,//单
		Double,//对儿
		Straight,//顺子3-<A 5
		DoubleStraight,//连队3-<A 6
		CThree,//三不带333444555 
		ThreeAndOne,//三带一33334444
		ThreeAndTwo,//三代二
		FourAndTwo,//四带二33334444 4带2对还是飞机
		FourAndFour,//四带二对
		Boom,//炸弹
		JokerBoom,//王炸
		CardTypeMax
	}CardsType;

	typedef struct CardStruct
	{
		//牌型
		CardType card;
		//花色对斗地主规则没有什么关系,只用于显示
		ColorType color;
		// 发牌存储
		UserType shuffle;
		//是否3张地主牌
		BOOL topbrand;
		//被出牌的轮次,0表示没有被出
		BYTE order;
		//被选中
		BOOL bsel;
	};
	
	//54扑克牌
	#define CardsCount 54
	CardStruct mCardsList[CardsCount];
	//提示牌结构体
	typedef struct TipsStruct
	{
		//牌数量
		BYTE count;
		//牌值CardType
		BYTE cards[CardsCount];
		//关键牌 22444和44555 大小关键在三张4和5
		BYTE hcard;
		//组牌类型CardsType
		BYTE type;
		//级别LevelType
		BYTE level;
		
		//cards的校验和
		INT checksum;
		//比自己大牌数量
		INT weight;
		//比自己小牌数量
		INT swatch;
		//平行组合
		TipsStruct *next;
	};

//==========================功能函数
void CardInit(void)
{	
	//扑克牌初始化 3333 4444 ... ... SJ LJ
	BYTE id=0;
	
	for(BYTE i=0;i<SJoker;i++)
	{
		for(BYTE j=0;j<Joker;j++)
		{
			mCardsList[id].card=(CardType)i;
			mCardsList[id].color=(ColorType)j;
			id++;
		}
	}
	
	mCardsList[id].card=SJoker;
	mCardsList[id].color=Joker;
	id++;

	mCardsList[id].card=LJoker;
	mCardsList[id].color=Joker;
}
/*
cards[CardMax]和cards[CardsCount]数组互转
0:CardsCount->CardMax
1:CardMax->CardsCount
*/
BYTE CardsTransform(BYTE *cards,BYTE Count,BYTE *uCards,BYTE uCount,BYTE type)
{
	BYTE count=0;

	//CardsCount->CardMax
	if(type==0)
	{
		//memset(uCards,0,uCount);
		for(BYTE i=0;i<Count;i++)
			uCards[cards[i]]++;
	}
	//CardMax->CardsCount
	else
	{
		for(BYTE i=0;i<uCount;i++)
			for(BYTE j=0;j<uCards[i];j++)
			{
				if(count<Count)
					cards[count]=i;
				
				count++;
			}
	}
	
	return count;
}
/// <summary>
/// 是否是单牌
/// 2
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsSingle(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if(Count == 1)
	{
		*hcard=cards[0];
		return TRUE;
	}
	else return FALSE;
}

/// <summary>
/// 判断是否是对儿
/// 22
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsDouble(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count == 2)
	{
		if (cards[0] == cards[1])
		{
			*hcard=cards[0];
			return TRUE;
		}
	}

	return FALSE;
}

/// <summary>
/// 是否是顺子
/// 如:23456
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsStraight(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count < 5 || Count > 12)
		return FALSE;

	for (INT i = 0; i < Count - 1; i++)
	{
		//不能超过A
		if (cards[i] > One || cards[i + 1] > One)
			return FALSE;
		
		if (cards[i + 1] - cards[i] != 1)
			return FALSE;
	}

	*hcard=cards[0];
	
	return TRUE;
}

/// <summary>
/// 是否是连对
/// 如:223344
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsDoubleStraight(BYTE *cards,BYTE Count,BYTE *hcard)
{
	// 牌数大于6且成对出现
	if (Count < 6 || Count % 2 != 0)
		return FALSE;

	for (INT i = 0; i < Count - 2; i += 2)
	{
		//对子
		if (cards[i] != cards[i + 1])
			return FALSE;
		
		if (cards[i + 2] - cards[i] != 1)
			return FALSE;
		//不能超过A
		if (cards[i] > One || cards[i + 2] > One)
			return FALSE;
	}

	//miss last check
	if (cards[Count-1] != cards[Count - 2])
		return FALSE;

	*hcard=cards[0];

	return TRUE;
}

/// <summary>
/// 是否是三不带以及飞机
/// 如:222 3,6,9,12,15,18
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsThree(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count < 3 || Count%3 != 0 )
		return FALSE;

	for(INT i=0;i<Count;i+=3)
	{
		if ((cards[i] != cards[i+1]) || (cards[i] != cards[i+2]))
			return FALSE;

		//检测飞机
		if(i>0)
		{
			if(cards[i]==Two)
				return FALSE;
		
			if(cards[i-1] != (cards[i]-1))
				return FALSE;
		}
	}

	*hcard=cards[0];
	
	return TRUE;
}

/// <summary>
/// 是否是三带一
/// 如:2224 4,8,12,16,19
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsThreeAndOne(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count < 4 || Count%4 != 0 )
		return FALSE;
	
	INT nThree=0,card,total;
	
	total=Count/4;
	
	for(INT i=0;i<Count;)
	{
		if(2+i<Count&&cards[i]==cards[1+i]&&cards[i]==cards[2+i])
		{
			//222333444555 222
			if(nThree==0||card>One||cards[i]>One||card!=(cards[i]-nThree))
			{
				nThree=1;
				card=cards[i];
			}
			else nThree++;

			//333444555666
			if(nThree==total)
			{
				*hcard=card;
				return TRUE;
			}
			
			i+=3;
		}
		else i++;
	}
	
	return FALSE;
}

/// <summary>
/// 是否是三带二
/// 如:22233 5,10,15,20
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
//333+王炸?
BOOL IsThreeAndTwo(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count < 5 || Count%5 != 0)
		return FALSE;
	
	//max 5
	INT nThree=0,card,nTwo=0;
	
	for(INT i=0;i<Count;)
	{
		//4条4444555666
		if(3+i<Count&&cards[i]==cards[1+i]&&cards[i]==cards[2+i]&&cards[i]==cards[3+i])
		{
			nTwo+=2;
			i+=4;
		}
		//3条3334442222
		else if(2+i<Count&&cards[i] == cards[1+i]&&cards[i] == cards[2+i])
		{
			if(nThree==0)card=cards[i];
			//大于One或者不连续
			else if(card>One||cards[i]>One||card!=(cards[i]-nThree))
				return FALSE;

			nThree++;
			i+=3;
		}
		//2条
		else if(1+i<Count&&cards[i]==cards[1+i])
		{
			nTwo++;
			i+=2;
		}
		else return FALSE;
	}
	
	//三条和对子都不够
	if(nThree==nTwo)
	{
		*hcard=card;	
		return TRUE;
	}
	
	return FALSE;
}

/// <summary>
/// 是否是四带二
/// 如:344445
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsFourAndTwo(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count != 6)
		return FALSE;
	
	for(INT i=0;i<3;i++)
	{
		if(cards[i]==cards[1+i]
			&&cards[i]==cards[2+i]
			&&cards[i]==cards[3+i])
		{
			*hcard=cards[i];
			return TRUE;
		}
	}

	return FALSE;
}

/// <summary>
/// 是否是四带二对
/// 如:33444455 44446666是否支持
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsFourAndFour(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count != 8)
		return FALSE;
	
	// 四对
	if( cards[0]==cards[1]
		&&cards[2]==cards[3]
		&&cards[4]==cards[5]
		&&cards[6]==cards[7])
	{
		//已经排好次序
		if(cards[0]==cards[2]&&cards[4]!=cards[6]) // 4个在前面
		{
			*hcard=cards[0];
			return TRUE;
		}
		else if(cards[2]==cards[4])// 4个在中间
		{
			*hcard=cards[2];
			return TRUE;
		}
		else if(cards[4]==cards[6]&&cards[0]!=cards[2]) // 4个在后面
		{
			*hcard=cards[4];
			return TRUE;
		}
		else if(cards[0]==cards[2]&&cards[4]==cards[6]) // 两个炸弹
		{
			if(cards[0]>cards[4])*hcard=cards[0];
			else *hcard=cards[4];
			return TRUE;
		}
	}
	
	return FALSE;
}


/// <summary>
/// 判断是否是炸弹
/// 如:4444
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsBoom(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count != 4)
		return FALSE;
	
	if(cards[0]==cards[1]
		&&cards[0]==cards[2]
		&&cards[0]==cards[3])
	{
		*hcard=cards[0];
		return TRUE;
	}

	return FALSE;
}

/// <summary>
/// 判断是不是王炸
/// 如:大王小王
/// </summary>
/// <param name="cards">选择的手牌</param>
/// <returns></returns>
BOOL IsJokerBoom(BYTE *cards,BYTE Count,BYTE *hcard)
{
	if (Count != 2)
		return FALSE;

	if (cards[0] == SJoker && cards[1] == LJoker)
	{
		*hcard=cards[0];
		return TRUE;
	}

	return FALSE;
}

/// <summary>
/// 判断能否出牌
/// </summary>
/// <param name="cards">要出的牌</param>
/// <param name="type">出牌类型</param>
/// <returns>能否出牌</returns>
BYTE CanPop(BYTE *cards,BYTE Count,BYTE *hcard)
{
	BYTE type = None;

	switch (Count)						// 牌数
	{
		case 1:
			if (IsSingle(cards,Count,hcard))
			{
				type = Single;
			}
			break;
		case 2:
			//优先王炸
			if (IsJokerBoom(cards,Count,hcard))   
			{
				type = JokerBoom;
			}
			else if (IsDouble(cards,Count,hcard))		  
			{
				type = Double;
			}
			
			break;
		case 3: 							
			if (IsThree(cards,Count,hcard))
			{
				type = CThree;
			}
			break;
		case 4:
			// 优先考虑炸弹
			if (IsBoom(cards,Count,hcard))
			{
				type = Boom;
			}
			else if (IsThreeAndOne(cards,Count,hcard))
			{
				type = ThreeAndOne;
			}
			break;
		case 5:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			else if (IsThreeAndTwo(cards,Count,hcard))
			{
				type = ThreeAndTwo;
			}
			break;
		case 6:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			else if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			else if(IsFourAndTwo(cards,Count,hcard))
			{
				type = FourAndTwo;
			}
			else if (IsThree(cards,Count,hcard))
			{
				type = CThree;
			}
			break;
		case 7:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			break;
		case 8:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			else if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			else if (IsThreeAndOne(cards,Count,hcard))
			{
				type = ThreeAndOne;
			}
			else if(IsFourAndFour(cards,Count,hcard))
			{
				type = FourAndFour;
			}
			
			break;
		case 9:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			else if (IsThree(cards,Count,hcard))
			{
				type = CThree;
			}
			break;
		case 10:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			else if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			else if (IsThreeAndTwo(cards,Count,hcard))
			{
				type = ThreeAndTwo;
			}
			break;
		case 11:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			break;
		case 12:
			if (IsStraight(cards,Count,hcard))
			{
				type = Straight;
			}
			else if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			// 444 555 666 777 > 777 888 999 345
			else if (IsThree(cards,Count,hcard))
			{
				type = CThree;
			}
			else if (IsThreeAndOne(cards,Count,hcard))
			{
				type = ThreeAndOne;
			}
			
			break;
		case 13:
			break;
		case 14:
			if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			break;
		case 15:
			if (IsThree(cards,Count,hcard))
			{
				type = CThree;
			}
			else if(IsThreeAndTwo(cards,Count,hcard))
			{
				type = ThreeAndTwo;
			}
			break;
		case 16:
			if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			else if (IsThreeAndOne(cards,Count,hcard))
			{
				type = ThreeAndOne;
			}
			break;
		case 17:
			break;
		case 18:
			if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			// 444 555 666 777 888 999 
			else if (IsThree(cards,Count,hcard))
			{
				type = CThree;
			}
			break;
		case 19:
			break;
		case 20:
			//33 44 55 66 77 88 99 1010 JJ QQ
			if (IsDoubleStraight(cards,Count,hcard))
			{
				type = DoubleStraight;
			}
			//3334445556667788991010
			else if(IsThreeAndTwo(cards,Count,hcard))
			{
				type = ThreeAndTwo;
			}
			//3334445556667778910JQ
			else if (IsThreeAndOne(cards,Count,hcard))
			{
				type = ThreeAndOne;
			}
			break;
		default:
			break;
	}
	
	return type;
}
void *InitTipsStruct()
{
	TipsStruct *p;

	p = (TipsStruct *)malloc(sizeof(TipsStruct));

	p->level=Level0;
	p->count=0;
	p->weight=0;
	p->swatch=0;
	p->checksum=0;
	
	p->next=NULL;

	return p;
}
/// <summary>
/// 对cards排序
/// </summary>
/// <param name="cards">对cards排序</param>
/// <returns></returns>
void SortMinToMax(BYTE *cards,BYTE Count)
{
	BYTE temp;
	
	for(BYTE i=0;i<Count;i++)
	{
		for(BYTE j=i+1;j<Count;j++)
		{
			if(cards[i]>cards[j])
			{
				temp=cards[i];
				cards[i]=cards[j];
				cards[j]=temp;
			}
		}
	}
}
/*
检查s是t否相同
*/
BOOL CheckEqual(BYTE *s,BYTE *t,BYTE Count,BOOL bsort)
{
	if(bsort)
	{
		SortMinToMax(s,Count);
		SortMinToMax(t,Count);
	}
	
	for(BYTE i=0;i<Count;i++)
	{
		if(s[i]!=t[i])
			return FALSE;
	}

	return TRUE;
}
/*
检查在链表l中有相同的项,没有则添加到末尾;
*/
void *AddTipsStruct(BYTE *cards,BYTE Count,BYTE type,BYTE hcard,TipsStruct *l)
{
	TipsStruct *p;

	p=l;

	while(p)
	{
		if(p->type==type
			&&p->count==Count
			&&CheckEqual(cards,p->cards,Count,FALSE))
		{
			//check same or not
			return l;
		}

		if(p->next == NULL)
		{
			p->next=(TipsStruct *)InitTipsStruct();
			p=p->next;
			break;
		}
		
		p=p->next;
	}

	if(p==NULL)
	{
		p=(TipsStruct *)InitTipsStruct();
		l=p;
	}

	p->count=Count;
	p->type=type;
	p->hcard=hcard;
	memcpy(p->cards,cards,Count);
	p->checksum=CheckSum(cards,Count);

	return l;
}
/*
把p拼接到l的后面;
*/
void *CombineList(TipsStruct *l,TipsStruct *p)
{
	if(p==NULL)return l;

	if(l==NULL)return p;
	
	TipsStruct *s=l;

	while(s->next)s=s->next;
	
	s->next=p;

	return l;
}
/*
比较s的牌是否比c的牌大
*/
BOOL CheckBigCards(TipsStruct *s,TipsStruct *c)
{
	if(s==NULL||s->type==None||c==NULL||c->type==None)return FALSE;

	//王炸最大,//炸弹
	if(s->type==JokerBoom || (s->type==Boom&&s->type>c->type))
		return TRUE;
	//相同牌型,相同长度,比较关键牌是否够大
	else if(s->type==c->type
		&&s->count==c->count
		&&s->hcard>c->hcard)
		return TRUE;	
	
	return FALSE;
}
/*
下标是卡牌值,数值是卡牌数量,比较卡牌的连续
*/
BOOL CheckContinuityM(BYTE *cards,BYTE Count,BYTE m)
{
	for(BYTE i=0;i<Count;i++)
	{
		if(cards[i]<m)return FALSE;
	}

	return TRUE;
}
/*
从card开始填充Count个连续相同的m进入cards
返回填充的数量;
*/
BYTE PadCards(BYTE *cards,BYTE Count,BYTE card,BYTE m)
{
	BYTE count=0;
	
	for(BYTE i=0;i<Count;i++)
		for(BYTE j=0;j<m;j++)
			cards[count++]=card+i;

	return count;
}
/*
获取顺子组合
*/
void *GetStraight(BYTE *cards)
{
	BYTE temp[CardsCount],count;

	TipsStruct *l=NULL;

	//单张起步5-12张34567 8910JQ KA
	for(INT i=5;i<=Two;i++)
	{
		for(INT j=Three;j<=(Two-i);j++)
		{
			if(CheckContinuityM(cards+j,i,1))
			{
				count=PadCards(temp,i,j,1);
				
				l=(TipsStruct *)AddTipsStruct(temp,count,Straight,temp[0],l);
			}
		}
	}
	
	return l;
}
/*
获取连对组合
*/
void *GetDoubleStraight(BYTE *cards)
{
	BYTE temp[CardsCount],count;

	TipsStruct *l=NULL;

	//起步3对
	for(INT i=3;i<=Two;i++)
	{
		for(INT j=Three;j<=(Two-i);j++)
		{
			if(CheckContinuityM(cards+j,i,2))
			{
				count=PadCards(temp,i,j,2);
				
				l=(TipsStruct *)AddTipsStruct(temp,count,DoubleStraight,temp[0],l);
			}
		}
	}
	
	return l;
}
/*
获取飞机组合
*/
void *GetCThree(BYTE *cards)
{
	BYTE temp[CardsCount],count;

	TipsStruct *l=NULL;

	//2个起步
	for(INT i=2;i<=Two;i++)
	{
		for(INT j=Three;j<=(Two-i);j++)
		{
			if(CheckContinuityM(cards+j,i,3))
			{
				count=PadCards(temp,i,j,3);
				l=(TipsStruct *)AddTipsStruct(temp,count,CThree,temp[0],l);
			}
		}
	}
	
	return l;
}
/*
获取同类数量的个数
*/
BYTE GetTypeCount(BYTE *cards,BYTE Count,BYTE m)
{
	BYTE count=0;
	
	for(BYTE i=0;i<Count;i++)
		if(cards[i]==m)count++;

	return count;
}
/*
删除cards中包含的uCards
*/
BOOL RemoveContain(BYTE *cards,BYTE *uCards,BYTE Count)
{
	for(BYTE i=0;i<Count;i++)
	{
		if(uCards[i]>cards[i])
		{
			return FALSE;
		}

		cards[i]-=uCards[i];
	}

	return TRUE;
}
//检查是否m的相同
BOOL bCheckM(BYTE *cards,BYTE Count,BYTE m)
{
	if(m>1)
	{
		//sortMinToMax(cards,Count);
		for(BYTE i=0;i<Count;)
		{
			for(BYTE j=0;j<m;j++)
			{
				if(cards[i]!=cards[i+j])
				{
					return FALSE;
				}
			}

			i+=m;
		}
	}

	return TRUE;
}
/*
获取组合,检查相同数量
*/
void *Combine(BYTE *cards,BYTE Count,BYTE n,BYTE m,BYTE type,BYTE hcard)
{
	if(n<1||Count<n||Count>CardsCount)return NULL;

	TipsStruct *l=NULL,*p=NULL;
	
	BYTE temp[CardsCount],wei[CardsCount],last=n-1;

	//temp = new BYTE[Count];
	//wei = new BYTE[Count];
/*
	1234556789
	方法从1234到6789,末位4逐一移位
	遇到5相同
*/
	//开始取n张牌开始查找组合
	for(INT i=0;i<n;i++)
	{
		wei[i]=i;
		temp[i]=cards[wei[i]];
	}
/*
	进位直到最后连续组合
	遍历末位0123,0124,0125
	前位进位0234,0235,判断最后2345结束
*/
	while(1)
	{
		//遍历末位
		BOOL bcheck=FALSE;
		
		for(;wei[last]<Count;wei[last]++)
		{
			//第二次相同继续下一位
			if(bcheck && temp[last]==cards[wei[last]])
				continue;

			bcheck=TRUE;
			
			temp[last]=cards[wei[last]];

			//check duizi
			if(bCheckM(temp,n,m))
			{
				if(l==NULL)
				{
					l=(TipsStruct *)AddTipsStruct(temp,n,type,hcard,NULL);
					p=l;
				}
				else
				{
					p->next=(TipsStruct *)AddTipsStruct(temp,n,type,hcard,NULL);
					p=p->next;
				}
			}
		}

		//末位
		wei[last]=Count-1;
		
		//从尾到头判断读是否已经连续
		BOOL breturn=TRUE;
		
		for(INT j=(last-1);j>=0;j--)
		{
			if(wei[j]!=(wei[j+1]-1))
			{
				breturn=FALSE;
				
				wei[j]++;
				//进位后复位后面的进入连续
				for(INT i=j+1;i<n;i++)
				{
					wei[i]=wei[i-1]+1;
				}

				//进位后检测没有变化
				BOOL same=TRUE;
				
				for(i=0;i<n;i++)
				{
					if(i<(n-1) && temp[i]!=cards[wei[i]])
						same=FALSE;

					temp[i]=cards[wei[i]];
				}

				//高位都相同继续进位
				if(same)
					wei[last]=Count;
				
				//继续移位
				break;
			}
		}

		//已经移位到最后
		if(breturn)break;
	}
	
	return l;	
}
/*

*/
void *GetCombine(TipsStruct *s,BYTE Count)
{
	INT count=Count;
	
	TipsStruct *p=s;
	
	while(p&&count>0)
	{
		count--;
		p=p->next;
	}

	return p;
}
/*
0->CardMax  ALL CARDS
CardMax .. S ID 
*/
void UpdateStraightList(TipsStruct *l,TipsStruct *s)
{
	TipsStruct *p=l;
	
	while(p)
	{
		for(INT i=0;i<p->count;i++)
		{
			p->cards[CardMax+i]=p->cards[i];
		}
			
		memset(p->cards,0,CardMax);
		
		for(i=0;i<p->count;i++)
		{
			TipsStruct *t=(TipsStruct *)GetCombine(s,p->cards[CardMax+i]);
			CardsTransform(t->cards,t->count,p->cards,CardMax,0);
		}

		p=p->next;
	}
}
/*
检查cards中是否包含uCards
*/
BOOL CheckContain(BYTE *cards,BYTE *uCards,BYTE Count)
{
	for(BYTE i=0;i<Count;i++)
	{
		if(uCards[i]>cards[i])
		{
			return FALSE;
		}
	}

	return TRUE;
}
/*
删除无效组合
*/
void *DelValidCombine(BYTE *cards,TipsStruct *l)
{
	TipsStruct *p,*pre=NULL;
	
	p=l;

	while(p)
	{
		if(CheckContain(cards,p->cards,Two)==FALSE)
		{
			//删除
			if(pre==NULL)
			{
				l=p->next;
				FreeTipsStruct(p);
				p=l;
			}
			else
			{
				pre->next=p->next;
				FreeTipsStruct(p);
				p=pre->next;					
			}
		}
		else
		{
			pre=p;
			p=p->next;
		}
	}

	return l;
}
//顺子特别排序,hcard存储了单张数量
//最少的3张,最多三张4个,较少对子
//减少的单张数量
//一个对子,至少2个单张
//减少一个3张至少2个单张
//减少1个炸弹至少3个单张
//综合1234 考虑飞机连对澹?
//评估顺子,连对,还是飞机结果剩余的单张和对子
// 34567 345667 3456667  34566667 对子是用一个多一个单张
// 345666789 3456666789
// 345566778 //消耗对子,保留最长
// 34567 78910JQ  34567 5678910JQ //两个段顺子,一个长顺子
// 3444555666778910QQQQ
// 3444555678 34445556788顺子必须消耗3个单张以上 <2对 <3飞机
//剩余单张是否有顺子
// 34567 8910JQ KA	 5-12张
//34567 45678 5 独立对子,重叠对子
//1、王炸
//2、先评估顺子,再评估连对,之后飞机,最后炸弹
//3、之后飞机炸弹配菜,剩余对子和单张
//产生的单张最少,尽量保存炸弹
//去头缩尾,看看有没有对子,3条,炸弹
//如果不要顺子,飞机可不可全部消耗
//单张最小,尽可能多留对子,留大单张
//34556677888999101010 34567 567888999101010 > 556677 34888999 101010
// 3344556667778910 -> 3344556677 678910
//	// A A K K K K Q J 10 10 9 8 6 6 6  A A K K K K 10 6 6 6  Q J 10 9 8 
	// [1] 4 [2] 2 [3] 0 [4] 1
	// [1] 1 [2] 1 [3] 0 [4] 1

	// K K K Q J J J 10 9 8 6 6 6 6 5 5 4 3 3 3
	// [1] 8 [2] 4 [3] 0 [4] 1
	// [1] 2 [2] 1 [3] 0 [4] 1
	// 2 2 A A K K K K J 5   Q J 10 9 8 7 6 5 4 3
BOOL CmpStraightResult(TipsStruct *t,TipsStruct *p,TipsStruct *pUser)
{
	if(t->weight>p->weight)
		return TRUE;
	
	else if(t->weight==p->weight
			&&t->level<p->level)
		return TRUE;
	
	else if(t->weight==p->weight
			&&t->level==p->level
			&&t->checksum<p->checksum)
		return TRUE;
	
	else if(t->weight==p->weight
			&&t->level==p->level
			&&t->checksum==p->checksum
			&&t->hcard>p->hcard)
		return TRUE;
	
	else if(t->weight==p->weight
			&&t->level==p->level
			&&t->checksum==p->checksum
			&&t->hcard==p->hcard
			&&t->type>p->type)
		return TRUE;

	return FALSE;
}
/*
获取最好的顺子组合
*/
void *GetBestStraight(BYTE *cards,TipsStruct *pUser)
{
	//评估顺子,连对,还是飞机结果剩余的单张和对子
	// 345666789 3456666789
	// 345566778 //消耗对子,保留最长
	// 34567 78910JQ  34567 5678910JQ //两个段顺子,一个长顺子
	// 3444555666778910QQQQ
	// 3444555678 34445556788顺子必须消耗3个单张以上 <2对 <3飞机
	//剩余单张是否有顺子
	// 34567 8910JQ KA	 5-12张
	//34567 45678 5 独立对子,重叠对子
	//1、王炸
	//2、先评估顺子,再评估连对,之后飞机,最后炸弹
	//3、之后飞机炸弹配菜,剩余对子和单张
	//产生的单张最少,尽量保存炸弹
	//去头缩尾,看看有没有对子,3条,炸弹
	//如果不要顺子,飞机可不可全部消耗
	TipsStruct *l=NULL,*s=NULL,*p=NULL;

	BYTE Cards[CardMax];
		
	memcpy(Cards,cards,CardMax);
	
	//单张最小,尽可能多留对子,留大单张
	//34556677888999101010 34567 567888999101010 > 556677 34888999 101010
	// 3344556667778910 -> 3344556677 678910
	INT Count=GetTypeCount(Cards,CardMax,3)+GetTypeCount(Cards,CardMax,4)*2;
	
	//if(GetTypeCount(Cards,CardMax,1)>Count)
	{
		//获取所有可能顺子组合
		l=(TipsStruct *)GetStraight(Cards);

		if(l==NULL)return NULL;
				
		//所有顺子编号0123456
		Count=0;
		
		p=l;
		
		while(p)
		{
			Count++;
			p=p->next;
		}

		BYTE *temp=new BYTE[Count];

		for(INT i=0;i<Count;i++)temp[i]=i;
		
		//对编号获取所有组合
		for(i=0;i<Count;i++)
		{
			//最多就4个顺子
			if(i<4)
			{
				s=(TipsStruct *)CombineList(s,(TipsStruct *)Combine(temp,Count,i+1,1,Straight,Three));
			}
			else break;
		}

		delete [] temp;
		temp=NULL;
		
		if(s)
		{		
			UpdateStraightList(s,l);

			s=(TipsStruct *)DelValidCombine(cards,s);

			TipsStruct *pBest=NULL,*t;

			t=(TipsStruct *)AddTipsStruct(cards,1,Straight,Three,NULL);

			UpdateStraightResult(cards,t);

			p=s;
			
			while(p)
			{
				memcpy(Cards,cards,CardMax);
				
				RemoveContain(Cards,p->cards,CardMax);

				UpdateStraightResult(Cards,p);
				
				if(pBest==NULL)
				{
					if(CmpStraightResult(t,p,pUser))
						pBest=p;
				}
				else
				{
					if(CmpStraightResult(pBest,p,pUser))
						pBest=p;
				}
				
				p=p->next;
			}	
					
			if(pBest)
			{			
				l=(TipsStruct *)RetainTips(pBest,l);
			}
			else 
			{
				FreeTipsList(l);
				l=NULL;
			}

			FreeTipsStruct(t);
			FreeTipsList(s);
		}
	}

	return l;
}
/*
检查cards中是否有card存在
*/
BOOL CheckExits(BYTE *cards,BYTE Count,BYTE card)
{
	for(BYTE i=0;i<Count;i++)
	{
		if(cards[i]==card)
		{
			return TRUE;
		}
	}

	return FALSE;
}
/*
删除小于pUser的牌组合
*/
void *RetainTips(TipsStruct *s,TipsStruct *l)
{
	TipsStruct *p,*pre=NULL;

	if(s==NULL)return l;

	BYTE count=0;
	
	p=l;

	while(p)
	{
		if(CheckExits(s->cards+CardMax,s->count,count)==FALSE)
		{
			//删除
			if(pre==NULL)
			{
				l=p->next;
				FreeTipsStruct(p);
				p=l;
			}
			else
			{
				pre->next=p->next;
				FreeTipsStruct(p);
				p=pre->next;					
			}
		}
		else
		{
			pre=p;
			p=p->next;
		}
		
		count++;
	}

	return l;
}
/*
从card开始填充Count个连续相同的m进入cards
返回填充的数量;

从cards取多少张牌
n取多少张牌
*/
BYTE CatCards(BYTE *cards,BYTE Count,BYTE *uCards,BYTE uCount,BYTE n)
{
	BYTE count=0,m;

	for(m=n;m<4;m++)
	{
		for(BYTE i=0;i<Count;i++)
		{
			if(cards[i]==m)
			{
				//对子特殊
				if(n==2&&m>n)
				{
					memset(uCards+count,i,n);
					count+=n;
				}
				else 
				{
					memset(uCards+count,i,m);
					count+=m;
				}
				
				if(count>=uCount)return uCount;
			}
		}
	}

	return count;
}
/*
删除小于pUser的牌组合
*/
void *DelSwatchTips(TipsStruct *l,TipsStruct *pUser)
{
	if(pUser==NULL)return l;

	TipsStruct *p,*pre=NULL;
	
	p=l;

	while(p)
	{
		if(CheckBigCards(p,pUser)==FALSE)
		{
			//删除
			if(pre==NULL)
			{
				l=p->next;
				FreeTipsStruct(p);
				p=l;
			}
			else
			{
				pre->next=p->next;
				FreeTipsStruct(p);
				p=pre->next;					
			}
		}
		else
		{
			pre=p;
			p=p->next;
		}
	}

	return l;
}
/*
获取快速组合牌;
1、取王炸
2、取顺子组合
3、取炸弹飞机三张连对
4、给炸弹飞机三张配料
不过应该是不是先取连对特别的策略
//获取连对4455666 445566 6 44666 55
// 4455666 999 445566 6999 or 44666 55999 rule
*/
void *QuickCombine(BYTE *cards,TipsStruct *pUser)
{
	BYTE lCards[CardMax],temp[CardsCount],cardstype[CardTypeMax];
	BYTE i=0;

	memcpy(lCards,cards,CardMax);
	memset(cardstype,0,CardTypeMax);

	if(pUser==NULL)
	{
		//牌权检查是否可以一把出完
		BYTE hcard,type,Count;
		
		Count=CardsTransform(temp,CardsCount,cards,CardMax,1);

		type=CanPop(temp,Count,&hcard);

		if(type>None)
		{
			return AddTipsStruct(temp,Count,type,hcard,NULL);
		}
	}

	TipsStruct *l=NULL,*p=NULL;

	//大小2222 AAAA KKKK QQQQ J
	//王炸不做单张和配菜,特殊情况需要两次牌权
	if(lCards[SJoker]&&lCards[LJoker])
	{
		temp[0]=SJoker;
		temp[1]=LJoker;
		p=(TipsStruct *)AddTipsStruct(temp,2,JokerBoom,temp[0],NULL);
		p->level=Level9;
		l=(TipsStruct *)CombineList(l,p);
		cardstype[JokerBoom]++;
		lCards[SJoker]=0;
		lCards[LJoker]=0;
	}

	//评估顺子,连对,还是飞机结果剩余的单张和对子
	// 345666789 3456666789
	// 345566778 //消耗对子,保留最长
	// 34567 78910JQ  34567 5678910JQ //两个段顺子,一个长顺子
	// 3444555666778910QQQQ
	// 3444555678 34445556788顺子必须消耗3个单张以上 <2对 <3飞机
	//剩余单张是否有顺子
	// 34567 8910JQ KA   5-12张
	//34567 45678 5 独立对子,重叠对子
	//1、王炸
	//2、先评估顺子,再评估连对,之后飞机,最后炸弹
	//3、之后飞机炸弹配菜,剩余对子和单张
	//产生的单张最少,尽量保存炸弹
	//去头缩尾,看看有没有对子,3条,炸弹
	//如果不要顺子,飞机可不可全部消耗
	//InitCharCard(lCards,CardMax,"2 2 A A K K K K Q J J 10 9 8 7 6 5 5 4 3");
	//InitCharCard(lCards,CardMax,"A A K K K K Q J 10 10 9 8 6 6 6");
	//InitCharCard(lCards,CardMax,"K K K Q J J J 10 9 8 6 6 6 6 5 5 4 3 3 3");
	// A A K K K K Q J 10 10 9 8 6 6 6 
	// K K K Q J J J 10 9 8 6 6 6 6 5 5 4 3 3 3
	// [1] 8 [2] 4 [3] 0 [4] 1
	// [1] 2 [2] 1 [3] 0 [4] 1
	// 2 2 A A K K K K J 5   Q J 10 9 8 7 6 5 4 3

	//排除顺子牌消耗对子最少
	p=(TipsStruct *)GetBestStraight(lCards,pUser);

	l=(TipsStruct *)CombineList(l,p);

	while(p)
	{
		memset(temp,0,CardMax);
		CardsTransform(p->cards,p->count,temp,CardMax,0);
		RemoveContain(lCards,temp,CardMax);
		p=p->next;
	}
	
	// 炸弹
	for(i=0;i<SJoker;i++)
	{
		if(lCards[i]==4)
		{
			memset(temp,i,4);
			p=(TipsStruct *)AddTipsStruct(temp,4,Boom,i,NULL);
			p->level=Level8;
			l=(TipsStruct *)CombineList(l,p);
			cardstype[Boom]++;
			lCards[i]=0;
		}
	}

	//飞机
	l=(TipsStruct *)CombineList(l,(TipsStruct *)GetCThree(lCards));

	// 三张
	for(i=0;i<SJoker;i++)
	{
		if(lCards[i]==3)
		{
			memset(temp,i,4);
			p=(TipsStruct *)AddTipsStruct(temp,3,CThree,i,NULL);
			p->level=Level1;
			l=(TipsStruct *)CombineList(l,p);

			p=(TipsStruct *)AddTipsStruct(temp,1,Single,i,NULL);
			p->level=Level7;
			l=(TipsStruct *)CombineList(l,p);

			p=(TipsStruct *)AddTipsStruct(temp,2,Double,i,NULL);
			p->level=Level7;
			l=(TipsStruct *)CombineList(l,p);
			
			cardstype[CThree]++;
			lCards[i]=0;
		}
	}
	
	//获取连对4455666 445566 6 44666 55
	// 4455666 999 445566 6999 or 44666 55999 rule
	p=(TipsStruct *)GetDoubleStraight(lCards);
		
	l=(TipsStruct *)CombineList(l,p);
	//排除连对牌
	memset(temp,0,CardMax);

	while(p)
	{
		for(BYTE i=0;i<p->count;i++)
		{
			if(temp[p->cards[i]]==0)
				temp[p->cards[i]]=2;
		}
			
		p=p->next;
	}

	RemoveContain(lCards,temp,CardMax);
	
	// 4566678JJJ   45678 66JJJ
	//统计剩余的单张和对子
	for(i=0;i<CardMax;i++)
	{
		//单张
		if(lCards[i]==1)
			cardstype[Single]++;
		//对子
		if(lCards[i]==2)
			cardstype[Double]++;
	}

	//飞机配菜
	p=l;
	while(p)
	{
		if(p->type==CThree)
		{
			INT count=(p->count/3);

			if(CatCards(lCards,CardMax,temp,count,1)>=count)
			{
				memcpy(temp+count,p->cards,p->count);
				
				count+=p->count;
				
				l=(TipsStruct *)AddTipsStruct(temp,count,ThreeAndOne,p->hcard,l);
				//l=(TipsStruct *)CombineList(l,p);
			}

			count=(p->count*2/3);

			if(CatCards(lCards,CardMax,temp,count,2)>=count)
			{
				memcpy(temp+count,p->cards,p->count);
				
				count+=p->count;
				
				TipsStruct *t;
				t=(TipsStruct *)AddTipsStruct(temp,count,ThreeAndTwo,p->hcard,NULL);
				t->level=Level1;
				l=(TipsStruct *)CombineList(l,t);
			}
		}
		
		p=p->next;
	}

	//还有剩余单张
	if(cardstype[CThree]>0&&(cardstype[Single]>0||cardstype[Double]>0))
	{
		//一人一个
		p=l;
		while(p)
		{
			if(p->type==CThree&&p->count==3)
			{
				//先消耗单张
				if(cardstype[Single]>0)
				{
					for(BYTE i=0;i<CardMax;i++)
					{
						if(lCards[i]==1)
						{
							memset(temp,i,1);
							memcpy(temp+1,p->cards,p->count);
							
							l=(TipsStruct *)AddTipsStruct(temp,4,ThreeAndOne,p->hcard,l);
							lCards[i]=0;
							cardstype[Single]--;
							break;
						}
					}
				}
				//再消耗对子
				else if(cardstype[Double]>0)
				{
					for(INT i=0;i<CardMax;i++)
					{
						if(lCards[i]==2)
						{
							memset(temp,i,2);
							memcpy(temp+2,p->cards,p->count);
							l=(TipsStruct *)AddTipsStruct(temp,5,ThreeAndTwo,p->hcard,l);
							lCards[i]=0;
							cardstype[Double]--;
							break;
						}
					}
				}
			}

			p=p->next;
		}
	}

	//剩下的单张
	for(i=0;i<CardMax;i++)
	{
		if(lCards[i]==1)
		{
			memset(temp,i,4);
			l=(TipsStruct *)AddTipsStruct(temp,1,Single,i,l);
		}
	}

	//剩下的对子
	for(i=0;i<CardMax;i++)
	{
		if(lCards[i]>1)
		{
			memset(temp,i,4);
			p=(TipsStruct *)AddTipsStruct(temp,1,Single,i,NULL);
			p->level=Level1;
			l=(TipsStruct *)CombineList(l,p);
			
			l=(TipsStruct *)AddTipsStruct(temp,2,Double,i,l);
		}
	}

	if(cardstype[Boom]>0&&(cardstype[Single]>1||cardstype[Double]>0))
	{
		//一人一个
		p=l;
		while(p)
		{
			if(p->type==Boom)
			{
				//先消耗单张
				if(cardstype[Single]>1||cardstype[Double]>0)
				{
					INT count=4;
					memset(temp,p->hcard,count);
					
					for(INT i=0;i<CardMax;i++)
					{
						if(lCards[i]==1)
						{
							temp[count++]=i;
							lCards[i]=0;
							cardstype[Single]--;
							
							if(count==6)
							{
								TipsStruct * s;
								s=(TipsStruct *)AddTipsStruct(temp,6,FourAndTwo,p->hcard,NULL);
								s->level=Level1;
								l=(TipsStruct *)CombineList(l,s);
								break;
							}
						}
					}

					if(count<6&&cardstype[Double]>0)
					{
						for(INT i=0;i<CardMax;i++)
						{
							if(lCards[i]==2)
							{
								temp[count++]=i;
								temp[count++]=i;
								lCards[i]=0;
								cardstype[Double]--;
								
								if(count>=6)
								{
									TipsStruct * s;
									s=(TipsStruct *)AddTipsStruct(temp,6,FourAndTwo,p->hcard,NULL);
									s->level=Level1;
									l=(TipsStruct *)CombineList(l,s);
									break;
								}
							}
						}
					}
				}

				//再消耗对子可以有4带2或者优先4带2对尽可能多消耗
				if(cardstype[Double]>0)
				{
					INT count=4;
					memset(temp,p->hcard,count);
					
					for(INT i=0;i<CardMax;i++)
					{
						if(lCards[i]==2)
						{
							temp[count++]=i;
							temp[count++]=i;
							
							lCards[i]=0;
							cardstype[Double]--;

							if(count==8||cardstype[Double]==0)
							{
								TipsStruct * s;
								
								if(count==8)
									s=(TipsStruct *)AddTipsStruct(temp,8,FourAndFour,p->hcard,NULL);
								else 
									s=(TipsStruct *)AddTipsStruct(temp,6,FourAndTwo,p->hcard,NULL);

								s->level=Level1;
								l=(TipsStruct *)CombineList(l,s);
								
								break;
							}
						}
					}
				}
			}
			p=p->next;
		}
	}

	//去除小牌
	l=(TipsStruct *)DelSwatchTips(l,pUser);

	//level 最末尾
	UpdateLast(l);

	return l;
}
/*
更新根据level排序,后根据拍数量排序
*/
void UpdateLast(TipsStruct *l)
{
	TipsStruct *s;

	s=l;
	
	while(s)
	{
		TipsStruct *t=s->next;
		
		while(t)
		{
			if(t->level<s->level
				||(t->level==s->level
				   &&(s->count<t->count
				      ||(s->count==t->count&&CheckBigCards(s,t)))))
			{
				ExChange(s,t);
			}

			t=t->next;
		}
		
		s=s->next;
	}
}

运行结果:
Tips[0] Alive:D X 2 A K K K Q Q J 10 9 8 7 7 6 5 4 4 3
List:
id,s->count,s->level,s->weight,s->swatch:
1-5-0-0-0:3,4,5,6,7,
2-5-0-0-0:7,8,9,10,J,
3-4-0-1-6:4,K,K,K,
4-2-0-2-9:Q,Q,
5-1-0-1-13:A,
6-1-0-0-15:2,
7-5-1-1-6:Q,Q,K,K,K,
8-3-1-1-6:K,K,K,
9-1-1-4-10:Q,
10-2-7-2-9:K,K,
11-1-7-3-12:K,
12-2-9-0-52:X,D,
END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠木123456

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值