C语言麻将算法(胡牌算法)

#include"a.h"

int main()
{

	int pai[14] = { 0, };
	int i = 0;
	int sum = 0;	//总的分这里默认为三家
	int num = 0;	//应该所得到得分数
	printf("请选择底金:");
	scanf("%d",&DiJ);
	printf("本局底金为:%d\n", DiJ);

	
	/*************************************在此判断牌得张数*************************************/
	printf("------温馨提示:数字0,10,20,30为系统预留空间------\n");
	for (i = 0; i < 14; i++)
	{
		//依次输入手牌
		printf("please you majon ipt:");
		scanf("%d", &pai[i]);
		printf("rand = %d\n", pai[i]);

		
		if ((pai[i] == 0) || (pai[i] == 10) || (pai[i] == 20) || (pai[i] == 30) || (pai[i] > 37))	//在判断牌型时 根据宏定义的数据来进行判断 方便来做判断
		{
			printf("input majon_type is error....quit\n");
			return 0;
		}
	}
	mysort(pai, 14);

	
	for (i = 0; i < 14; i++)	//循环遍历输入的牌型 判断牌型是否成立若输入的手牌牌型大于4 则超出了麻将的牌数故直接退出
	{

		printf("%3d", pai[i]);
		aPAI[pai[i]]++;
		if (aPAI[pai[i]] > 4)
		{
			printf("\n");
			printf("you input pai %d greater than 4.....so...bai\n", pai[i]);
			return 0;

		}

	}
	


 	/*
	if (h258jiang(pai))
	{
		printf("\n");
		printf("win................258");
		system("pause");
		return 0;
	}
	else
	{
		printf("\n");
		printf("No Win\n");
		system("pause");
	}
	*/
	//豪华七对
	if (HHQD(pai))
	{
		printf("\n");
		printf("HHQD......\n");
		//胡牌算分
		Sleep(1000);
		num = DiJ * 15;
		sum = num * 3;
		printf("应得分:%d\n", num);
		Sleep(1000);
		printf("总得分:%d\n", sum);
		system("pause");
		return 0;
	}
	//七对
	if (QiDui(pai))
	{

		printf("\n");
		printf("QiDui...\n");
		//胡牌算分
		num = DiJ * 8;
		sum = num * 3;
		printf("应得分:%d\n", num);
		Sleep(1000);
		printf("总得分:%d\n", sum);
		system("pause");
		return 0;

	}
	//碰碰胡
	if (PPHU(pai))
	{
		printf("\n");
		printf("PPHU......\n");
		//胡牌算分
		num = DiJ * 12;
		sum = num * 3;
		printf("应得分:%d\n", num);
		Sleep(1000);
		printf("总得分:%d\n", sum);
		system("pause");
		return 0;
	}
	
	if (shisanyao(pai))
	{
		printf("\n");
		printf("十三幺\n");
		//胡牌算分
		num = DiJ * 13;
		sum = num * 3;
		printf("应得分:%d\n", num);
		Sleep(1000);
		printf("总得分:%d\n", sum);
		system("pause");
		return 0;
	}

	//平胡
	
	if (Hu(pai))
	{
		printf("\n");
		printf("Win 2333\n");
		//胡牌算分
		num = DiJ * 2;
		sum = num * 3;
		printf("应得分:%d\n", num);
		Sleep(1000);
		printf("总得分:%d\n", sum);
		system("pause");
		return 0;
	}
	else
	{
		printf("\n");
		printf("No Win\n");
		system("pause");
	}
	return 0;
}
//判断七对
int QiDui(int QiDui_Jiag[14])
{
	int i = 0;
	memset(aPAI, 0, sizeof(aPAI));
	for (i = 0; i < 14; i++)
	{
		//循环遍历手牌,将牌型各自+1
		aPAI[QiDui_Jiag[i]]++;
		printf("qidui[%d] = %d ---%d\n", i, QiDui_Jiag[i], aPAI[QiDui_Jiag[i]]);


		//判断牌型是否为将
		if (aPAI[QiDui_Jiag[i]] == 2)
		{
			aPAI[QiDui_Jiag[i]] -= 2;
			QiDui_Jiang++;


		}
		//判断牌型是否为4个 如为四个一样的牌型则QiDui_JIang+2;
		if (aPAI[QiDui_Jiag[i]] == 4 && aPAI[QiDui_Jiag[i]] > 3)	QiDui_Jiang += 2;

	}
	printf("QiDui_Jiang =%d\n", QiDui_Jiang);
	if (QiDui_Jiang == 7)	return 1;
	return 0;
}

int   Hu(int   PAI[14])
{	
	static   int   JIANG = 0;									
	int i;	  
	if (!Remain(PAI))   return   1;								//   递归退出条件:如果没有剩牌,则和牌返回。    

	for (i = 0; !aPAI[PAI[i]] && i<14; i++);					//   找到有牌的地方,i就是当前牌,   aPAI[PAI[i]]是个数    

	printf("i   =   %d\n", i);								    //   跟踪信息    
	
																//   4张组合(杠子)    
	if (aPAI[PAI[i]] == 4)									    //   如果当前牌数等于4张    
	{
		aPAI[PAI[i] ] = 0;										 //  除开全部4张牌    
		if (Hu(PAI))   return   1;								//   如果剩余的牌组合成功,和牌    
		aPAI[PAI[i]] = 4;										//   否则,取消4张组合    
	}

	//   3张组合(大对)    
	if (aPAI[PAI[i]] >= 3)										//   如果当前牌不少于3张    
	{
		aPAI[PAI[i]] -= 3;								      //   减去3张牌    
		if (Hu(PAI))   return   1;							  //   如果剩余的牌组合成功,和牌    
		aPAI[PAI[i]] += 3;                                   //   取消3张组合    
	}

	//   2张组合(将牌)    
	if (!JIANG   &&   aPAI[PAI[i]] >= 2)					//   如果之前没有将牌,且当前牌不少于2张    
	{
		JIANG = 1;											 //   设置将牌标志    
		aPAI[PAI[i]] -= 2;                                   //   减去2张牌    
		if (Hu(PAI))   return   1;							 //   如果剩余的牌组合成功,和牌    
		aPAI[PAI[i]] += 2;                                   //   取消2张组合    
		JIANG = 0;											//   清除将牌标志    
	}


	if (PAI[i]   >   JIUTONG_MAJIANG)         return   0;				  //   “东南西北中发白”没有顺牌组合,不和    

																			//   顺牌组合,注意是从前往后组合!    
	if (PAI[i] % 10 != 8 && PAI[i] % 10 != 9 &&								 //   排除数值为8和9的牌    
		aPAI[PAI[i]+1] && aPAI[PAI[i]+2])									  //   如果后面有连续两张牌    
	{
		aPAI[PAI[i]]--;
		PAI[PAI[i]+ 1 ]--;
		aPAI[PAI[i]+ 2 ]--;													    //   各牌数减1    
		if (Hu(PAI))   return   1;												//   如果剩余的牌组合成功,和牌    
		PAI[i]++;
		PAI[PAI[i] + 1]++;
		aPAI[PAI[i] + 2]++;														 //   恢复各牌数    
	}

	//   无法全部组合,不和!    
	return   0;
}

//   检查剩余牌数    
int   Remain(int   PAI[14])
{
	int   sum = 0;
	
	for (int i = 0; i<14; i++)
		sum += aPAI[PAI[i]];
	return   sum;
}

//豪华七对
int HHQD(int HHQD[14])
{
	int i = 0;
	int HH_QD = 0;
	int jiang = 0;
	//由于aPAI[38]为全局变量,则每次都需要把该数组内所有数据初始化为0;
	memset(aPAI, 0, sizeof(aPAI));
	for (i = 0; i < 14; i++)
	{	//循环遍历手牌,将牌型各自+1;
		aPAI[HHQD[i]]++;
		//当该牌型为4 则+1
		if (aPAI[HHQD[i]] == 4)
		{
			HH_QD++;
		}
		//判断该牌型是否有将
		if (!jiang && aPAI[HHQD[i]] == 2)
		{
			jiang++;
		}
	}
	if (HH_QD == 3 && jiang == 1)	return 1;
	return 0;
}

//PPH
int PPHU(int PPH[14])
{
	int i = 0;
	int PP_H = 0;
	int jiang = 0;
	//由于aPAI[38]为全局变量,则每次都需要把该数组内所有数据初始化为0;
	memset(aPAI, 0, sizeof(aPAI));
	for (i = 0; i<14; i++)
	{
		//循环遍历手牌,将牌型各自+1
		aPAI[PPH[i]]++;
		//当该牌型为2 则+1
		if (aPAI[PPH[i]] == 3)
		{
			aPAI[PPH[i]] -= 3;
			PP_H++;
		}
		//判断该牌型是否有将
		if (!jiang && aPAI[PPH[i]] == 2)
		{
			jiang++;
		}
	}
	//在这里判断该手牌是否有十四张牌....r如果没有则直接退出

	printf("PPH = %d,jiang = %d\n", PP_H, jiang);
	if (PP_H == 4 && jiang == 1)	return 1;

	return 0;
}

//十三幺
int shisanyao(int shisan[14])
{
	int i = 0;
	int majon = 0;
	int jiang = 0;
	memset(aPAI,0,sizeof(aPAI));
	
	for (i = 0; i < 14; i++)
	{
		aPAI[shisan[i]]++;
		//用条件语句来限制牌型
		if ((shisan[i] == YITIAO_MAJIANG) || (shisan[i] == JIUTIAO_MAJIANG) || (shisan[i] == YIWAN_MAJIANG) || \
			(shisan[i] == JIUWAN_MAJIANG)||(shisan[i] == YITONG_MAJIANG) || (shisan[i] == JIUTONG_MAJIANG) || (shisan[i]) > JIUTONG_MAJIANG)
		{		
			if (aPAI[shisan[i]] == 1)
			{
				
				continue;
			}
		}
		else if (aPAI[shisan[i]] == 2)
		{
			jiang++;	
		}
		else
		{
			return 0;
		}
		//在这里判断该手牌是否有十四张牌....r如果没有则直接退出
		if (jiang != 1)	return 0;
		printf("%d", jiang);
	}
	return 1;
}


//将258将牌单独用一个函数来存放
int isJiangPai(int pai)
{

	//将258将牌单独用一个函数来存放 如果该牌型里是否有258将
	if (pai == ERTIAO_MAJIANG) return 1;
	if (pai == WUTIAO_MAJIANG) return 1;
	if (pai == BATIAO_MAJIANG) return 1;

	if (pai == ERTONG_MAJIANG) return 1;
	if (pai == WUTONG_MAJIANG) return 1;
	if (pai == BATONG_MAJIANG) return 1;

	if (pai == ERWAN_MAJIANG) return 1;
	if (pai == WUWAN_MAJIANG) return 1;
	if (pai == BAWAN_MAJIANG) return 1;

	return 0;
}
//对输入的手牌进行排序(顺序)
void mysort(int * aa, int l)
{
	int tmp;
	int i = 0;
	int j = 0;
	for (i = 0; i<l; i++)
	{
		for (j = i + 1; j<l; j++)
		{
			if (aa[i] > aa[j])
			{
				tmp = aa[j];
				aa[j] = aa[i];
				aa[i] = tmp;
			}
		}
	}

}
/*


int PAI_Type(int PAI[38])	//PAI[38]1-9表示tiao 11-19表示万.........
{
	int begin = YITIAO_MAJIANG;
	int end = BAIBAN_MAJIANG;	//表示麻将最后一张
	int len = 0;	//表示麻将的长度
	int i = 0;
	int i_pai[38];
	memset(i_pai,0,sizeof(i_pai));
	memcpy(i_pai,PAI,sizeof(int)* 38);

	//遍历牌型
	for (i = YITIAO_MAJIANG; i < 38; i++)	
	{
		while (i > JIUTONG_MAJIANG)
		{
			if (PAI[i] < 2)	return 0;					//由于在有风的情况下如果不为刻字和将则不能胡牌直接返回0;
			continue;
		}
		if (PAI[i] == 2)
		{
			PAI[i] -= 2;
		}
		
		//if (PAI[DONGFENG_MAJIANG] < 2)	return 0;	//由于在有风的情况下如果不为刻字和将则不能胡牌直接返回0;


	}
}
*/

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值