一手牌(规则请见:http://dpk888.com/school/discussions/%E4%B8%80%E6%89%8B%E7%89%8C%E7%9A%84%E7%89%8C%E5%9E%8B-poker-hands#per_page=10),枚举 + 模拟,关键是明白其桌子上的牌相当于一个栈,只有丢掉手里相应数量的牌才可以从栈中依次抽出相应数量的牌来维持手里始终有五张牌,依此枚举。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
int poker_cmp(const void *a, const void *b)
{
return strcmp((char *)a,(char *)b);
}
int ff, flag[11];
char a[6][3], b[11][3];
char s[9][20] = {"highest-card", "one-pair", "two-pairs", "three-of-a-kind",
"straight", "flush", "full-house", "four-of-a-kind", "straight-flush"
};
int judge_flush() // 判断 同花
{
int i;
for(i = 0; i < 4; i++)
if(a[i][1] != a[i + 1][1])
return 0;
return 1;
}
int judge_straight() // 判断 顺子
{
if(a[0][0] == '1' && a[1][0] == ':' && a[2][0] == ';' && a[3][0] == '<' && a[4][0] == '=') // 注意特殊情况的判定,原因请见规则
return 1;
for(int i = 0; i < 4; i++)
if(a[i][0] != a[i + 1][0] - 1)
return 0;
return 1;
}
int judge_kind_4() // 判断 四条
{
int i;
for(i = 0; i < 3; i++)
if(a[i][0] != a[i + 1][0])
break;
if(i == 3)
return 1;
for(i = 1; i < 4; i++)
if(a[i][0] != a[i + 1][0])
return 0;
return 1;
}
int judge_full_house() // 判断 葫芦
{
if(a[0][0] == a[1][0] && a[1][0] == a[2][0] && a[3][0] == a[4][0])
return 1;
if(a[0][0] == a[1][0] && a[2][0] == a[3][0] && a[3][0] == a[4][0])
return 1;
return 0;
}
int judge_kind_3()// 判断 三条
{
if(a[0][0] == a[1][0] && a[1][0] == a[2][0] )
return 1;
if(a[1][0] == a[2][0] && a[2][0] == a[3][0] )
return 1;
if(a[2][0] == a[3][0] && a[3][0] == a[4][0] )
return 1;
return 0;
}
int judge_two_pairs() // 判断 两对
{
if(a[0][0] == a[1][0] && a[2][0] == a[3][0] )
return 1;
if(a[0][0] == a[1][0] && a[3][0] == a[4][0] )
return 1;
if(a[1][0] == a[2][0] && a[3][0] == a[4][0] )
return 1;
return 0;
}
int judge_pair() // 判断 一对
{
for(int i = 0; i < 4; i++)
if(a[i][0] == a[i + 1][0])
return 1;
return 0;
}
int solve()
{
int flush = judge_flush();
int straight = judge_straight();
if(flush && straight)
return 8;
int kind_4 = judge_kind_4();
if(kind_4)
return 7;
int full_house = judge_full_house();
if(full_house)
return 6;
if(flush)
return 5;
if(straight)
return 4;
int kind_3 = judge_kind_3();
if(kind_3)
return 3;
int two_pairs = judge_two_pairs();
if(two_pairs)
return 2;
int pair = judge_pair();
if(pair)
return 1;
return 0;
}
int subset_2()
{
int ct = 0, f;
for(int i = 0; i < 10; i++)
if(flag[i])
strcpy(a[ct++], b[i]);
else if(ct == 5)
break;
qsort(a, 5, sizeof(a[0]), poker_cmp);
f = solve();
if(f > ff)
ff = f;
return ff;
}
int subset() // 枚举子集
{
int fi[5];
for(fi[0] = 0; fi[0] < 10; fi[0]++)
for(fi[1] = fi[0] + 1; fi[1] < 10; fi[1]++)
if(fi[0] != fi[1])
for(fi[2] = fi[1] + 1; fi[2] < 10; fi[2]++)
if(fi[0] != fi[2] && fi[1] != fi[2])
for(fi[3] = fi[2] + 1; fi[3] < 10; fi[3]++)
if(fi[0] != fi[3] && fi[1] != fi[3] && fi[2] != fi[3])
for(fi[4] = fi[3] + 1; fi[4] < 10; fi[4]++)
if(fi[0] != fi[4] && fi[1] != fi[4] && fi[2] != fi[4] && fi[3] != fi[4])
{
int fct = 0;
for(int i = 0; i < 5; i++)
if(fi[i] < 5)
++fct;
if(fi[4] >= 10 - fct) // 保证只有丢掉相应数量的手牌才可以从桌子上抽取相应数量的牌
break;
memset(flag, 0, sizeof(flag));
flag[fi[0]] = 1;
flag[fi[1]] = 1;
flag[fi[2]] = 1;
flag[fi[3]] = 1;
flag[fi[4]] = 1;
int f = subset_2();
if(f == 8)
return 8;
}
return 0;
}
int main()
{
#ifdef test
freopen("in.txt", "r", stdin);
#endif
char str[50];
while(gets(str) != NULL)
{
for(int i = 0; i < 10; i++)
sscanf(str + 3 * i, "%[^ ]",b[i]);
printf("Hand: ");
for(int i = 0; i < 5; i++)
printf("%s ", b[i]);
printf("Deck: ");
for(int i = 5; i < 10; i++)
printf("%s ", b[i]);
printf("Best hand: ");
for(int i = 0; i < 10; i++) // 为了判断方便,可以将‘A’‘T’‘J’‘Q’‘K’转化为‘1’‘:’‘“’‘<’‘=',其ASCll码依次增加
if(b[i][0] == 'A')
b[i][0] = '1';
else if(b[i][0] == 'T')
b[i][0] = ':';
else if(b[i][0] == 'J')
b[i][0] = ';';
else if(b[i][0] == 'Q')
b[i][0] = '<';
else if(b[i][0] == 'K')
b[i][0] = '=';
ff = 0;
subset();
printf("%s\n", s[ff]);
}
return 0;
}