// Poker Hands (扑克牌型)
// PC/UVa IDs: 110202/10315, Popularity: C, Success rate: average Level: 2
// Verdict: Accepted
// Submission Date: 2011-05-23
// UVa Run Time: 0.008s
//
// 版权所有(C)2011,邱秋。metaphysis # yeah dot net
//
// 计算每手牌的值,先将牌按从大到小排序。可以将牌的数值看成15进制系统。对于一手牌按 15
// 进制来计算它的值,将其转换成一个整数来比较大小。例如:
//
// 2H 3H 4H 5H 6H
//
// 是同花顺,则将其转换成15进制数为:
//
// 6 * 15^4 + 5 * 15^3 + 4 * 15^2 + 3 * 15^1 + 2 * 15^0 = (65432)(15)
//
// 每一种牌的类型表示成进位,如 STRAIGHT_FLUSH 的进位为 8,则最终牌面值乘以 15^8,保证了类型
// 较高的牌面值肯定会大于类型较低的牌面值。则 2H 3H 4H 5H 6H 的最终牌面值为:
//
// (6 * 15^4 + 5 * 15^3 + 4 * 15^2 + 3 * 15^1 + 2 * 15^0) * 15^8 =
// (6543200000000)(15)
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cmath>
using namespace std;
#define HIGH_CARD 0
#define PAIR 1
#define TWO_PAIR 2
#define THREE_KIND 3
#define STRAIGHT 4
#define FLUSH 5
#define FULL_HOUSE 6
#define FOUR_KIND 7
#define STRAIGHT_FLUSH 8
#define TIE 0
#define BLACK_WIN 1
#define WHITE_WIN 2
#define BASE 15
#define CARDS 5
#ifndef DEBUG_MODE
// #define DEBUG_MODE
#endif
#ifdef DEBUG_MODE
string type[STRAIGHT_FLUSH + 1] = {"HIGH_CARD", "PAIR", "TWO_PAIR", "THREE_KIND",
"STRAIGHT", "FLUSH", "FULL_HOUSE", "FOUR_KIND", "STRAIGHT_FLUSH"};
#endif
// 将牌面字符转换成数字。T = 10,J = 11,Q = 12,K = 13,A = 14。
int convert(char c)
{
string cards = "23456789TJQKA";
for (int i = 0; i < cards.length(); i++)
if (c == cards[i])
return (i + 2);
}
// 排序比较函数,大的数在前。
bool cmp(int a, int b)
{
return a > b;
}
// 对牌面值按从大到小排序。
void sort_card(string hands[], int *card)
{
for (int i = 0; i < CARDS; i++)
card[i] = convert(hands[i][0]);
sort(card, card + CARDS, cmp);
}
// 按类型 type 将牌面值转换成一个整数值。
long long unsigned get_score(int *card, int type)
{
long long unsigned score = 0;
for (int i = 0; i < CARDS; i++)
score = score * BASE + card[i];
return score * pow(BASE, type);
}
// 交换两个数。
void swap(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
// 判断牌面属于何种类型。确定类型后,将关键牌移往前面,非关键牌按从大到小顺序排列。
long long unsigned card_type(int *card, int type, string hands[])
{
bool flag;
char suit;
switch (type)
{
case HIGH_CARD:
return get_score(card, HIGH_CARD);
case PAIR:
for (int i = 0; i < CARDS; i++)
if (card[i] == card[i + 1])
{
if (i > 0)
{
swap(card[i], card[0]);
swap(card[i + 1], card[1]);
}
return get_score(card, PAIR);
}
break;
case TWO_PAIR:
for (int i = 0; i < CARDS - 2; i++)
if (card[i] == card[i + 1])
{
for (int j = i + 2; j < CARDS; j++)
if (card[j] == card[j + 1])
{
if (i > 0)
{
swap(card[i], card[0]);
swap(card[i + 1], card[1]);
}
if (j > 2)
{
swap(card[j], card[2]);
swap(card[j + 1], card[3]);
}
return get_score(card, TWO_PAIR);
}
}
break;
case THREE_KIND:
for (int i = 0; i < CARDS - 2; i++)
if (card[i] == card[i + 2])
{
if (i > 0)
{
swap(card[i], card[0]);
swap(card[i + 1], card[1]);
swap(card[i + 2], card[2]);
}
return get_score(card, THREE_KIND);
}
break;
case STRAIGHT:
flag = true;
for (int i = 0; i < CARDS - 1; i++)
if (card[i] != (card[i + 1] + 1))
{
flag = false;
break;
}
if (flag)
return get_score(card, STRAIGHT);
break;
case FLUSH:
flag = true;
suit = hands[0][1];
for (int i = 1; i < CARDS; i++)
if (suit != hands[i][1])
{
flag = false;
break;
}
if (flag)
return get_score(card, FLUSH);
break;
case FULL_HOUSE:
if (card[0] == card[2] && card[3] == card[4])
return get_score(card, FULL_HOUSE);
if (card[0] == card[1] && card[2] == card[4])
{
swap(card[2], card[0]);
swap(card[3], card[1]);
swap(card[4], card[2]);
return get_score(card, FULL_HOUSE);
}
break;
case FOUR_KIND:
for (int i = 0; i < CARDS - 3; i++)
if (card[i] == card[i + 3])
{
if (i > 0)
{
swap(card[i], card[0]);
swap(card[i + 1], card[1]);
swap(card[i + 2], card[2]);
swap(card[i + 3], card[3]);
}
return get_score(card, FOUR_KIND);
}
break;
case STRAIGHT_FLUSH:
if (card_type(card, STRAIGHT, hands) &&
card_type(card, FLUSH, hands))
return get_score(card, STRAIGHT_FLUSH);
break;
}
return 0;
}
// 获取一手牌的最大类型及其值。
long long unsigned get_value(string hands[])
{
int card[5];
sort_card(hands, card);
long long unsigned value = 0;
for (int i = 8; i >= 0; i--)
{
value = card_type(card, i, hands);
if (value)
{
#ifdef DEBUG_MODE
cout << endl;
cout << "<Debug Begin>" << endl;
for (int j = 0; j < CARDS; j++)
cout << hands[j] << " ";
cout << endl;
for (int j = 0; j < CARDS; j++)
cout << card[j] << " ";
cout << endl;
cout << "CARD TYPE: " << type[i] << endl;
cout << "VALUE: " << value << endl;
cout << "<Debug End>" << endl;
cout << endl;
#endif
return value;
}
}
}
// 比较两手牌的大小,直接比较其值的大小即可。
int compare_card(string f_hands[], string s_hands[])
{
long long unsigned f_value, s_value;
f_value = get_value(f_hands);
s_value = get_value(s_hands);
return (f_value == s_value) ? (TIE) : ((f_value > s_value) ?
(BLACK_WIN) : (WHITE_WIN));
}
int main(int ac, char *av[])
{
string f_hands[5], s_hands[5], line;
string info[3] = { "Tie.", "Black wins.", "White wins." };
while (getline(cin, line))
{
istringstream iss(line);
for (int i = 0; i < 5; i++)
iss >> f_hands[i];
for (int i = 0; i < 5; i++)
iss >> s_hands[i];
cout << info[compare_card(f_hands, s_hands)] << endl;
}
return 0;
}
UVa Problem 10315 Poker Hands (扑克牌型)
最新推荐文章于 2024-11-06 07:09:03 发布