UVa 181 - Hearts

contents

  1. 1. Problem
  2. 2. Input
  3. 3. Output
  4. 4. Sample input
  5. 5. Sample output
  6. 6. Solution

Problem

There are 52 playing cards in a pack, divided into suits, and, within suits, into denominations. The suits are (in order, lowest to highest) Clubs, Diamonds, Hearts and Spades, abbreviated C, D, H and S. The 13 denominations (or face values) are (from lowest to highest): 2, 3, 4, 5, 6, 7, 8, 9, 10 (T), Jack (J), Queen (Q), King (K) and Ace(A). A higher card will beat a lower card in the same suit, but will not usually beat any other card in a different suit. An exception to this is the trump suit–if a suit is designated to be a trump suit (by whatever means the rules of the game allow), then any card of that suit will beat any card of any other suit.

撲克共有 52 張牌,總共有 4 種花色 (C < D < H < S, 梅花 < 方塊 < 紅心 < 黑桃),每 1 種花色有 13 張牌,由小到大的點數分別是 2, 3, 4, 5, 6, 7, 8, 9, 10 (T), Jack (J), Queen (Q), King (K) and Ace(A),點數大的可以勝過點數小的。在遊戲中可以選定 王牌 的花色,王牌可以贏過任一其他花色的牌。

A simplified version of an old card game called Hearts is played as follows. The dealer deals cards clockwise, one by one, face downward, to four other players and himself, starting with the player on his left, who thus gets the first card, followed by the sixth, and so on, while the dealer gets the fifth card, followed by the tenth, and so on. When each player has 10 cards there will be two left–these are exposed and the suit of the one of higher denomination determines the trump suit. If there is a tie, then the highest ranking suit becomes the trump suit.

Hearts 是一款早期的簡化版卡牌遊戲,總共有 5 名玩家,發牌者將會順時針從自己的左手邊第一個玩家依序發給每一個玩家,因此發牌者自己將會拿到第 5 張、第 10 張、 … 等。最後,每名玩家將會有 10 張牌,剩下的兩張牌點數高的那張牌的花色將是王牌花色,如果點數相同,則原本由原本花色大的被選為王牌花色。

A game consists of 10 tricks, each containing 5 cards, one from each player. For each trick, one player leads, i.e. plays a card face up on the table, the rest of the players then `follow’, in clockwise order. The player to the dealer’s left leads to the first trick, thereafter the winner of each trick leads to the next trick. A player must follow suit if possible, i.e. play a card of the same suit as the one lead. If he cannot, then he must trump it (play a card of the designated trump suit). If he cannot trump it (because he has no cards in the trump suit), he discards a card. If a trick is trumped, then the person playing the highest trump wins the trick, otherwise the person playing the highest card of the correct suit wins it.

這場遊戲共計 10 輪,每一輪每名玩家各出 1 張牌,因此共計 5 張。在每一輪中,將會有一名玩家擔任 首發,首發將決定這一輪的花色,而剩餘的玩家按照順時針順序出牌。在這一輪中,獲勝者將成為下一輪的首發,並且將可以得到這一輪所有紅心的分數。每名玩家必須盡可能出這一輪所需要的花色,如果沒有所需花色,打出王牌將可以勝過其他非王牌的出牌,如果有數名玩家接打出王牌,則出點數較高王牌的玩家獲勝。

Strategies are as follows:

  • Leader: The leader always plays the highest card in his hand. If there is a tie and one of the cards is a trump card, then he leads the trump, otherwise he plays the highest ranking suit.
  • Follower: If possible he must play the highest card in his hand of the correct suit. If he has no cards in that suit then he plays the highest trump he has. If he cannot trump it he plays the highest card in his hand, breaking ties as previously specified.

策略如下所述:

  • 首發:將會從發中挑一個最高點數的牌,如果點數相同,則會先挑王牌花色的那一張,如果沒有王牌花色,則出花色排名最高的那一張。
  • 跟隨者:將打出該輪所需花色的最高點數牌。如果沒有所需花色,將會打出手上點數最高的王牌,如果還是沒有王牌,則將打出最高點數的牌,若點數相同將打出最高花色的那張。

When all the tricks have been played, each player examines the tricks he has taken and scores the face value of any Heart he has (Jack counts 11, Queen counts 12, King counts 13 and Ace counts 14). This score is recorded.

在每一輪,獲勝者將會拿到該輪出牌 5 張中紅心的點數,並且加入到自己的得分中。

Write a program to simulate the playing of this game.

Input

Input will consist of a series of decks of cards, each deck spread over four lines as shown below. The file will be terminated by a line consisting of a single #.

Output

Output will consist of a series of lines, one for each deck in the input. Each line will consist of 5 numbers reflecting the scores of the individual players, starting with the dealer and proceeding clockwise through the rest of the players. Each score will consist of a number right justified in a field of width 3.

Sample input

1
2
3
4
5
TS QC 8S 8D QH 2D 3H KH 9H 2H TH KS KC
9D JH 7H JD 2S QS TD 2C 4H 5H AD 4D 5D
6D 4S 9S 5S 7S JS 8H 3D 8C 3S 4C 6S 9C
AS 7C AH 6H KD JC 7D AC 5C TC QD 6C 3C
#

Sample output

1
22 0 68 0 14

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int suitW(char c) {
switch(c) {
case 'C':return 0;
case 'D':return 1;
case 'H':return 2;
case 'S':return 3;
}
}
int cardW(char c) {
switch(c) {
case '2'...'9':return c - '0';
case 'T':return 10;
case 'J':return 11;
case 'Q':return 12;
case 'K':return 13;
case 'A':return 14;
}
}
char decideTrump(const char c1[], const char c2[]) {
if(cardW(c1[0]) != cardW(c2[0]))
return cardW(c1[0]) > cardW(c2[0]) ? c1[1] : c2[1];
return suitW(c1[1]) > suitW(c2[1]) ? c1[1] : c2[1];
}
int leaderCmp(string c1, string c2) {
if(cardW(c1[0]) != cardW(c2[0]))
return cardW(c1[0]) > cardW(c2[0]);
return suitW(c1[1]) > suitW(c2[1]);
}
string leaderPlay(vector<string> &hand, char trump) {
sort(hand.begin(), hand.end(), leaderCmp);
int h = hand[0][0];
for(vector<string>::iterator it = hand.begin();
it != hand.end(); it++) {
if((*it)[1] == trump && (*it)[0] == h) {
string ret = *it;
hand.erase(it);
return ret;
}
}
string ret = hand[0];
hand.erase(hand.begin());
return ret;
}
string followerPlay(vector<string> &hand, char suit, char trump) {
sort(hand.begin(), hand.end(), leaderCmp);
for(vector<string>::iterator it = hand.begin();
it != hand.end(); it++) {
if((*it)[1] == suit) {
string ret = *it;
hand.erase(it);
return ret;
}
}
for(vector<string>::iterator it = hand.begin();
it != hand.end(); it++) {
if((*it)[1] == trump) {
string ret = *it;
hand.erase(it);
return ret;
}
}
string ret = hand[0];
hand.erase(hand.begin());
return ret;
}
int main() {
char deckCard[52][128];
const int tricks = 10;
do {
for(int i = 0; i < 52; i++) {
scanf("%s", deckCard[i]);
if(!strcmp(deckCard[i], "#"))
return 0;
}
vector<string> hand[5];
for(int i = 0, j = 0; i < 50; i++, j = (j+1)%5) {
hand[j].push_back(deckCard[i]);
}
char trump = decideTrump(deckCard[50], deckCard[51]);
int leader = 0;
int scores[5] = {};
for(int i = 0; i < tricks; i++) {
vector< pair<string, int> > desk;
desk.push_back(make_pair(leaderPlay(hand[leader], trump), leader));
char suit = desk[0].first[1];
for(int j = (leader + 1)%5, k = 0; k < 4; j = (j+1)%5, k++) {
desk.push_back(make_pair(followerPlay(hand[j], suit, trump), j));
}
int maxCardW = -1;
for(int j = 0; j < desk.size(); j++) {
// printf("PLAYER %d play %s\n", desk[j].second + 1, desk[j].first.c_str());
if(desk[j].first[1] == trump && suit != trump) {
suit = trump;
maxCardW = cardW(desk[j].first[0]);
leader = desk[j].second;
}
if(suit == desk[j].first[1] && cardW(desk[j].first[0]) > maxCardW) {
maxCardW = cardW(desk[j].first[0]);
leader = desk[j].second;
}
}
/*
printf("PLAYER %d is the winner\n", leader + 1);
for(int j = 0; j < 5; j++) {
for(int k = 0; k < hand[j].size(); k++)
printf(" %2d%c ", cardW(hand[j][k][0]), hand[j][k][1]);
puts("");
}*/
for(int j = 0; j < desk.size(); j++) {
if(desk[j].first[1] == 'H') {
// printf("GET %d\n", cardW(desk[j].first[0]));
scores[leader] += cardW(desk[j].first[0]);
}
}
}
printf("%3d", scores[4]);
for(int i = 0; i < 4; i++)
printf("%3d", scores[i]);
puts("");
} while(true);
return 0;
}