本文持续更新地址:https://haoqchen.site/2018/11/08/card-judge/
题目描述
这里进行游戏的扑克牌共有52张,共有2,3,4,5,6,7,8,9,T,J,Q,K,A这13种类型的牌,每一种有4张(因此在一个牌组中,同种类的牌最多只会出现4张)。此处为了方便,不考虑花色的情况,即对于每一种牌,如K,4张K的地位是等价的。不同种的牌之间有大小的关系,为A>K>Q>J>T>9>8>7>6>5>4>3>2。
5张牌所能构成的牌组有以下几种情况:
四条:5张牌中有4张相同的种类。如AAAAQ。当两副牌均为四条时,相同的那个种类的牌较大者较大。如AAAAQ大于KKKKQ。当两副牌均为四条且相同的种类的牌也相同时,第5张牌较大者较大。如AAAAQ大于AAAAJ。
葫芦(三带二):5张牌中共有两种牌,一种有3张,一种有2张。如AAAKK。当两副牌均为葫芦时,3张的那种牌较大者较大。如AAAQQ大于KKKQQ。当两副牌均为葫芦且3张的牌相同时,2张的牌较大者较大。如AAAKK大于AAAQQ。
顺子:5张牌是大小连续的。如34567。注意此处有唯一一个特殊情况A2345也是顺子,但此刻A视为1,因此这个顺子中最大的牌是5。同时TJQKA也是顺子,此时A依然按照单张牌中最大的计算。当两副牌均为顺子时,最大的牌较大者较大。如23456大于A2345;789TJ大于45678;TJQKA则是最大的顺子。
三条:5张牌中有3张相同的牌,剩下的2张与这3张牌种类不同且互相种类不同。如AAAKQ。当两副牌均为三条时,相同的那个种类的牌较大者较大。如AAAKQ大于KKKAQ。当两副牌均为三条且相同种类的牌相同时,剩下2张牌中最大的那张较大者较大。如AAAKJ大于AAAQJ。当两副牌均为三条且相同种类的牌相同且剩下2张牌中最大的那张也相同时,第5张牌较大者较大。如AAAKQ大于AAAKJ。
两对:5张牌中共有三种牌,其中有两种各有2张,第三种有1张。如AAKKQ。此处定义“对子”为一个由两张相同的牌组成的牌组。如AAKKQ就有一个对子AA和另一个对子KK。对子的大小由组成对子的牌的种类决定。如AA大于KK。当两副牌均为两对时,最大的对子较大者较大。如AAQQJ大于KKQQJ。当两副牌均为两对且最大的对子相同时,第二个对子较大者较大。如AAKKJ大于AAQQJ。当两副牌均为两对且两个对子都相同时,第5张牌较大者较大。如AAKKQ大于AAQQJ。
一对:5张牌中有一个对子,剩下的3张牌种类与这个对子不同且互相种类不同。如AAKQJ。当两副牌均为一对时,对子较大者较大。如AAQJT大于KKQJT。当两副牌均为一对且对子相同时,比较剩下的3张牌。优先比较3张中最大的,如AAKJT大于AAQJT。若最大的相同,则比较第2大的,如AAKQT大于AAKJT。否则比较最小的,如AAKQJ大于AAKQT。
散牌:牌组不符合任意以上的牌型则为散牌。散牌无法构成顺子且5张牌种类均不同。如AKJ54。当两副牌均为散牌时,优先比较最大的。如A7654大于K7654。若最大的相同则比较次大的。如AK765大于AQ765。若再相同则比较第3大的,以此类推。
不同的牌组类型中,四条>葫芦>顺子>三条>两对>一对>散牌。小A作为一个新手,并不能熟练的记忆上述的牌型。现在有两副牌组,小A并没有办法快速的判断哪一个更大,你能帮助他吗?
输入
第一行是一个不超过100的正整数n,表示一共有n组测试数据。每一组数据包含两行,分别代表两个牌组。
接下来2n行,每2行代表两幅要进行比较的牌组。每副牌组由5个被空格隔开的正整数表示。其中10代表T,11代表J,12代表Q,13代表K,14代表A。因此五个数将会在2到14之间。
输入保证合法,如不会出现2到14以外的数,同样的数也不会出现超过4次。
输出
输出共n行,每行一个整数0或1或2。对于每组测试数据,1代表第1个牌组较大,2代表第2个牌组较大,0代表一样大。
示例
样例输入
3
2 3 4 5 6
4 4 4 4 11
2 3 8 9 10
10 9 8 3 2
4 4 7 8 7
4 4 8 7 8
样例输出
2
0
2
代码
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
enum Result{EQUAL, WIN, LOSE};
enum CardStyle{SINGLE, ONE_PAIR, TWO_PAIR, THREE, CONTINUES, CUCURBIT, FOUR};
CardStyle get_CardStyle(map<int, int>& _map)
{
int map_size = _map.size();
if (map_size == 5){
//sort(_map.begin(), _map.end());
auto ite1 = _map.begin();
auto ite2 = _map.begin();
while (++ite2 != _map.end()){
if (ite2->first != (ite1->first + 1))
break;
++ite1;
}
if (ite2 == _map.end())
return CONTINUES;
else{
ite1 = _map.end();
--ite1;
if (ite1->first == 14){
ite2 = _map.begin();
int i = 0;
for (; i < 4; ++i){
if (ite2->first != (i + 2))
break;
++ite2;
}
if (i == 4){
_map.erase(ite1);
return CONTINUES;
}
}
return SINGLE;
}
}
else if (map_size == 4)
return ONE_PAIR;
else if (map_size == 3){
for (auto val : _map){
if (val.second == 2)
return TWO_PAIR;
else if (val.second == 3)
return THREE;
}
}
else if (map_size == 2){
for (auto val : _map){
if (val.second == 2)
return CUCURBIT;
else if (val.second == 3)
return CUCURBIT;
else if (val.second == 4)
return FOUR;
}
}
}
Result compare(int* a, int* b, int num)
{
if (num == 0)
return EQUAL;
for (int i = 0; i < num; ++i){
if (a[i] > b[i])
return WIN;
else if (a[i] < b[i])
return LOSE;
else{
return compare(++a, ++b, --num);
}
}
}
Result cards_judge(int* a, int* b)
{
map<int, int> a_map;
map<int, int> b_map;
for (int i = 0; i < 5; ++i){
++a_map[a[i]];
++b_map[b[i]];
}
CardStyle a_style = get_CardStyle(a_map);
CardStyle b_style = get_CardStyle(b_map);
if (a_style > b_style)
return WIN;
else if (a_style < b_style)
return LOSE;
else{
auto ite_a = a_map.begin();
auto ite_b = b_map.begin();
int a_pair[5];
int b_pair[5];
int ai, bi = 3;
switch (a_style){
case SINGLE:
ai = 4;
bi = 4;
while (ite_a != a_map.end()){
a_pair[ai--] = ite_a->first;
b_pair[bi--] = ite_b->first;
++ite_a;
++ite_b;
}
return compare(a_pair, b_pair, 5);
break;
case ONE_PAIR:
ai = 3;
bi = 3;
while (ite_a != a_map.end()){
if (ite_a->second == 1)
a_pair[ai--] = ite_a->first;
else
a_pair[0] = ite_a->first;
if (ite_b->second == 1)
b_pair[bi--] = ite_b->first;
else
b_pair[0] = ite_b->first;
++ite_a;
++ite_b;
}
return compare(a_pair, b_pair, 4);
break;
case TWO_PAIR:
ai = 1;
bi = 1;
while (ite_a != a_map.end()){
if (ite_a->second == 2)
a_pair[ai--] = ite_a->first;
else
a_pair[2] = ite_a->first;
if (ite_b->second == 2)
b_pair[bi--] = ite_b->first;
else
b_pair[2] = ite_b->first;
++ite_a;
++ite_b;
}
return compare(a_pair, b_pair, 3);
break;
case THREE:
ai = 2;
bi = 2;
while (ite_a != a_map.end()){
if (ite_a->second == 1)
a_pair[ai--] = ite_a->first;
else
a_pair[0] = ite_a->first;
if (ite_b->second == 1)
b_pair[bi--] = ite_b->first;
else
b_pair[0] = ite_b->first;
++ite_a;
++ite_b;
}
return compare(a_pair, b_pair, 3);
break;
case CONTINUES:
ite_a = a_map.end();
ite_b = b_map.end();
--ite_a;
--ite_b;
if (ite_a->first > ite_b->first)
return WIN;
else if (ite_a->first < ite_b->first)
return LOSE;
else
return EQUAL;
break;
break;
case CUCURBIT:
while (ite_a != a_map.end()){
if (ite_a->second == 2)
a_pair[1] = ite_a->first;
else
a_pair[0] = ite_a->first;
if (ite_b->second == 2)
b_pair[1] = ite_b->first;
else
b_pair[0] = ite_b->first;
++ite_a;
++ite_b;
}
return compare(a_pair, b_pair, 2);
return WIN;
case FOUR:
while (ite_a != a_map.end()){
if (ite_a->second == 1)
a_pair[1] = ite_a->first;
else
a_pair[0] = ite_a->first;
if (ite_b->second == 1)
b_pair[1] = ite_b->first;
else
b_pair[0] = ite_b->first;
++ite_a;
++ite_b;
}
return compare(a_pair, b_pair, 2);
break;
}
}
}
int main(int argc, char** argv)
{
int n = 0;
int number[2][5] = {0};
cin >> n;
if (n > 100 || n <= 0)
return 1;
int* result = new int[n];
for (int i = 0; i < n; ++i){
for (int i = 0; i < 2; ++i){
for (int j = 0; j < 5; ++j){
cin >> number[i][j];
}
}
result[i] = cards_judge(number[0], number[1]);
}
for (int i = 0; i < n; ++i){
cout << result[i] << endl;
}
delete[] result;
return 0;
}
思路
首先利用map对5张牌进行分类统计。然后通过get_CardStyle获得5张牌的类型,是散牌、一对还是两对三对。。。。。该函数通过判断map的size及特点进行分类。分类完之后比较两人的牌的类型,这里用枚举enum来定义牌类型,按顺序排好后直接比较大小即可。如果两人牌类型一样,则根据类型switch处理方案。但是比较思路都是一致的,将需要比较的数字依次放入a_pair、b_pair中。其实map中的数字已经进行了排序了的,拿一对这种情况来说,将一对的数字放入a_pair[0],将剩下三个数中最大的放入a_pair[1]、次大的放入a_pair[2]、然后是a_pair[3]。对b做同样处理之后通过compare函数进行比较得到结果。