背景
- 麻将胡牌规则
m * AAA + n * ABC + AA
m 和 n 可 为0
- 麻将中的花色有万(1-9),条(1-9),筒(1-9),风(东南西北中發白)
实现算法
当玩家摸牌之后,玩家手中会有14张牌,使用一个vector<int>
来保存玩家手中所有的牌,将一万到九万映射到1-9,一条到九条映射到21-29,一筒到九筒映射到31-39,再用100-700表示风牌。
经过上面的转换,得到一个长度为14的vector<int>
。
- 依次取出vec中成对的牌AA
- 判断此时vec是否满足m * AAA + n * ABC
- 对于vec的第一张牌,其有可能在AAA中,也有可能在ABC中,也有可能都不在
- 当其在AAA中时,取出vec中的AAA,判断剩下的vec是否满足m * AAA + n * ABC
- 当其在ABC中时,取出vec中的ABC,判断剩下的vec是否满足m * AAA + n * ABC
- 当其都不在时,返回false
可以看到,通过简单的递归,即可判断麻将是否胡牌。
实现代码
判断vec是否满足m * AAA + n * ABC 的函数
static bool isFormat(std::vector<int> vec){
if(vec.size() == 0){
return true;
}else if(vec.size() < 3 || vec.size() % 3 != 0){
return false;
}
bool res = false;
// vec[0] 位于 AAA型
if(vec[0] == vec[1] && vec[1] == vec[2]){
std::vector<int> left(vec.begin()+3,vec.end());
if(isFormat(left)){
res = true;
}
}
// vec[0] 位于 ABC型
std::vector<int> left;
int i=0,j=0;
for(int k=1;k<vec.size();++k){
if(vec[k]==vec[0]+1){
i=k;
}
if(vec[k]==vec[0]+2){
j=k;
}
}
if(i!=0 && j!=0){
std::vector<int> left;
for(int k=1;k<vec.size();++k){
if(k==i || k==j){
continue;
}
left.push_back(vec[k]);
}
if(isFormat(left)){
res = true;
}
}
return res;
}
结束语
为了锻炼代码能力,用c++写了个麻将游戏,很不美观,但是基本框架搭好了,跟朋友玩了两局,都是我赢了,然后ta鄙视我说这是开发者的阴谋。
没有开杠,没有碰牌,没有屁胡,只有自摸……