还说不是炸胡
麻将是国粹,是成都的生活重心。作为一个成都人,一定要把麻将发扬光大。
现在组织有一个重要的任务交给你:请你设计一个判断是否炸胡的程序。
什么是炸胡? 炸胡,是指达不到胡牌条件就把牌推倒了。 那什么是胡牌呢? 胡牌代表你赢了。
当你手上的牌符合三种胡牌牌型之一时,就是胡牌,可以推倒牌收钱啦。
三种胡牌牌型
- 普通牌型,14张牌,形如:
3+3+3+3+2
。其中数字2代表两张相同的牌可成一组,形如XX。数字3代表三张相同或者连续的牌可成一组,形如XXX、XYZ。 - 龙七对,14张形如:
2+2+2+2+2+2+2
。 - 带杠,即普通牌型里三张一样的牌XXX可以升级成XXXX,称为一道杠。每多一道杠,牌总数可以增加一张。最多可以有4道杠,因此带杠的胡牌,牌总数最多可以达18张。
牌的表示方式
下面我们用 ABCDEFGHI
代表一到九萬,abcdefghi
代表一到九条,123456789
代表一到九饼。
先来练习一下:
ABCeee345456DD
胡牌,组牌方式为 ABC+eee+345+456+DD,普通牌型。ABeeee345456DD
炸胡,因为AB两张牌未能形成组牌。AAAABC123456333
炸胡,虽然看似组牌OK(AAA+ABC+124+345+456+333)但是不符合任何一种胡牌牌型。AADDFF1133aagg
胡牌,暗七对。AAAABBBBCCCCDDDD88
胡牌,3+3+3+3+2牌型,升级了4道杠。AAA123789
炸胡,不符合任何一种牌型。AAA111345666DEF88
炸胡,不符合任何一种牌型。
学会了吗?
现在给你一副牌,请用你的程序来判断这副牌是胡牌还是炸胡。
输入说明
程序从命令行参数取得输入数据。
测试数据为一个字符串,代表一副牌,请参考上面牌的表示方式。 注意:牌序是乱的。
输出说明
若这副牌达到胡牌条件,输出GOOD
,炸胡则输出BAD
。
示例
测试数据:123BCD999abd66
预期输出:BAD
思路::
1.贷gang
2.一对将
3.取3个一样或连续,满足则不要了,直到没牌
先getchar将牌放到
1.存放在一个18数组char a里面,不管重复,最多18个牌,计数,判定1条件14 17
/sort排序,需要?
2.再来个数组int b计算每个牌个数对应同万条0-8,9-17,18-26,27个牌一眼看出,比如b【0】=2,说明同1有2个
for循环a数组,switch(a【i】),比如a【i】==‘1’,就b【0】++
所以,如果加一个sort排序a,按1 A a, 11AAABBBaaabbb,排序好之后,哦,还是不可以节省break,还是要for循环. 所以还是不排序省一点运行时间
3.判定条件二,for循环数组b,if》=2,OK,并且让他减2
这里有个问题????????????????????,要找到正确的将,因为可能有很多牌都不止》=2,所以要先找=2的,等于二的也不一定,比如123345 AABCD DDD,正确的将是AA,但遍历会先找到33,
所以遍历所有将牌的情况来解决这里的问号
并且这里D不是gang
如果是正确的gang牌还要先减去gang-4再判定2,3条件 ,怎样找到是真正的gang???????????????????所以找到所有的4张牌的,分为-4与不-4,(ps:但还有种胡是七对,拿来单独判定吧,遍历 有对y++, if y==7就可以,不可以正常判定,goto) 15-4,11等于9+2,真正的gang,16-8=8=6+2,两gang,17-12=5=3+2,3gang,还有4gang,但不带gang就是14张,所以之间for加起来,if =14,不带,》14带,减4再找牌判定
所以根据牌的个数解决这里的问好
4。找到了将,判定三张一样的,有就-3,然后判定三张连续的,whileb数字不全为0,即还有牌,for找到》=1的,下表为x,然后if(x+1和+2也》=1),分别减去1
主要看看这里如何遍历所有对牌
for (i = 0; i < 27; i++)
c[i] = b[i];
for (int k = 0; k < 27; k++)
{
if (c[k] < 2)
continue;
c[k] -= 2;
for (i = 0; i < 27; i++) {//除开三个牌一样的
if (c[i] == 3)
c[i] -= 3;
}
for (i = 0; i < 27; i++) {
if ((c[i] >= 1) && (c[i + 1] >= 1) && (c[i + 2] >= 1)) {
c[i] -= 1;
c[i + 1] -= 1;
c[i + 2] -= 1;
}
}
sum = 0;
for (i = 0; i < 27; i++)
sum += c[i];
for (i = 0; i < 27; i++)
c[i] = b[i];
if (!sum) {
printf("GOOD");
return 0;
}
}
此时已经没有了gang
效率不高,27个对牌都测试一下,但还好,没有就continue
主要在这个思路
每次取对牌前都要个原始的牌,每次都是重新测试,所有要找一个备份!!!
#include<stdlib.h>
int main(int argc,char *argv[])
{
char *majong = argv[1];
int b[27] = { 0 };
int i,sum=0,dui=0,gang=0;
for (i = 0; i <18 ; i++)
{
char ch = majong[i];
switch (ch)
{
case '1':b[0]++; break;case '2':b[1]++; break;case '3':b[2]++; break;case '4':b[3]++; break;case '5':b[4]++; break;
case '6':b[5]++; break;case '7':b[6]++; break;case '8':b[7]++; break;case '9':b[8]++; break;case 'A':b[9]++; break;
case 'B':b[10]++; break;case 'C':b[11]++; break;case 'D':b[12]++; break;case 'E':b[13]++; break;case 'F':b[14]++; break;
case 'G':b[15]++; break;case 'H':b[16]++; break;case 'I':b[17]++; break;case 'a':b[18]++; break;case 'b':b[19]++; break;
case 'c':b[20]++; break;case 'd':b[21]++; break;case 'e':b[22]++; break;case 'f':b[23]++; break;case 'g':b[24]++; break;
case 'h':b[25]++; break;case 'i':b[26]++; break;
default: break;//其他的直接过滤掉,比如后面的\0和未知?
}
}
for (i = 0; i < 27; i++) {
sum += b[i];
}
if (sum < 14) {
printf("BAD");
return 0;
}
else if (sum == 14) {//14情况下龙七对判定
for (i = 0; i < 27; i++) {
if (b[i] == 2)
dui++;
else if (b[i] == 4)
dui += 2;
}
if (dui == 7) {
printf("GOOD");
return 0;
}
}
else if (sum == 15||sum==16||sum==17||sum==18) {//杠
for (i = 0; i < 27; i++) {
if (b[i] == 4) {
gang++;
b[i] = 0;
}//这里有问题,万一去掉的不是正确的gang
else {
printf("BAD");
return 0;
}
}
}
//现在已经去掉了gang并且龙七对情况已经说明,现在找将牌
int c[27] = { 0 };
for (i = 0; i < 27; i++)
c[i] = b[i];
for (int k = 0; k < 27; k++)
{
if (c[k] < 2)
continue;
c[k] -= 2;
for (i = 0; i < 27; i++) {//除开三个牌一样的
if (c[i] == 3)
c[i] -= 3;
}
for (i = 0; i < 27; i++) {
if ((c[i] >= 1) && (c[i + 1] >= 1) && (c[i + 2] >= 1)) {
c[i] -= 1;
c[i + 1] -= 1;
c[i + 2] -= 1;
}
}
sum = 0;
for (i = 0; i < 27; i++)
sum += c[i];
for (i = 0; i < 27; i++)
c[i] = b[i];
if (!sum) {
printf("GOOD");
return 0;
}
}
printf("BAD");
return 0;
}