虽然单花色胡牌算法面试时写出来了,但是完整的胡牌算法却没有写,既然遇到了,秉着不抛弃不放弃的精神,当然不能原谅懒惰的自己了。下面这篇为一个完整的胡牌算法。
胡牌规则除了以下几点,其余与单花色胡牌规则一致:
1.东南西北中发,只能三个相同的牌才能进行组合,不允许与不同的牌进行组合
2.牌的花色可能有多种
分析:
这里由于涉及到多花色的情况,我们可以将它当作是单花色的一个扩展。即,只要从牌中取出一对将牌后,将剩余的牌按照花色分别判断是否符合规则即可。其中judgeLeft函数为单花色中使用的函数。代码如下:enum eHuaseType
{
EN_WANZI = 0, // 万字
EN_TIAOZI, // 条字
EN_BINGZI, // 饼字
EN_FENG, // 风
EN_HUASE_COUNT // 花色的种类数};#define MAX_LENGTH_OF_HUASE (10)// 多申请一些内存,方便取值// 假定牌对应的数字如下:1~9为万字,11~19为条字,21~29为饼字,31~37为东南西北中发白bool judgeLeftHuase(int *arr, int len, eHuaseType etype)
{ // 如果是万、条、饼,则按照单花色判断
if (etype
{ return judgeLeft(arr, len);
} // 如果是东南西北中发白,则判断是否是3个相同的牌
for (int i = 0; i
{ if (arr[i] == 0)
{ continue;
} if (arr[i] != 3)
{ return false;
}
} return true;
}bool completeHupai(int *arr, int len)
{ if (len
{ return false;// 牌的长度小于5,或者去除将牌后,长度不是三的倍数
} int atrans[EN_HUASE_COUNT][MAX_LENGTH_OF_HUASE]; int atmps[EN_HUASE_COUNT][MAX_LENGTH_OF_HUASE]; memset(atrans, 0, sizeof(atrans));
eHuaseType eType = EN_HUASE_COUNT; for (int i = 0;i
{
eType = (eHuaseType)(arr[i] / MAX_LENGTH_OF_HUASE); // 取牌的类型
atrans[eType][arr[i] - 1 - eType *10]++; // 将出现的牌进行次数累计
} // 遍历 atrans 进行取将
for (int i = 0;i
{ memcpy(atmps, atrans, sizeof(atrans)); if (atmps[i/ MAX_LENGTH_OF_HUASE][i%MAX_LENGTH_OF_HUASE]
{ continue;
}
atmps[i / MAX_LENGTH_OF_HUASE][i % 10] -= 2; // 取将完成,判断剩余的牌是否符合规则
for (int j = 0;j
{ // 如果不符合规则,则重新取将
if (!judgeLeftHuase(atmps[j],MAX_LENGTH_OF_HUASE,j))
{ break;
} // 如果所有的花色都判断OK,则这副牌可以胡
if (j == EN_HUASE_COUNT - 1)
{ return true;
}
}
} return false;
}