1.扑克问题
问题描述:
在扑克中,牌的类型包括:A(1),2,3,4,5,6,7,8,9,T(10),J(11),Q(12),K(13),D(小鬼devilkin),B(大鬼Belial)。
请做一个简单的程序,输入两张牌的字符,比如"2"和"K",判断牌的大小,规则如下:
B>D>2>A>K>Q>J>10....>3 最小的为3
判断规则:比较cFirstCard和cSecondCard,如果FirstCar大,那么返回1;如果相同,返回0;如果FirstCar小,返回-1。
要求实现函数:
int CompareOneCard(char cFirstCard, char cSecondCard)
【输入】 char cFirstCard:需要比较的第一张牌
char cSecondCard: 需要比较的第二张牌
注意:输入的为字符’A’,’2’,…,’9’,’T’,’J’,’Q’,’K’,’D’,’B’
【返回】 int类型:返回两张牌的比较结果
注意:不用考虑输入的合法性,这个由函数的使用者保证。输入的牌均为字符’1’,’2’…’9’,大写的’A’,’T’,’J’,’Q’,’K’,’D’,’B’。
举例:
输入:’4’、’5’,返回:-1
输入:’6’、’6’,返回:0
2. 干瞪眼(30分)
问题描述:
在成都,流行一种扑克游戏叫“干瞪眼”。使用扑克牌,包括:A(1),2,3,4,5,6,7,8,9,T(10),J(11),Q(12),K(13)。
注意:10用T替换,这里暂时不考虑大鬼和小鬼。
两手牌的大小规则如下:
a) 单牌:4比3大,5比4大,只有两张牌刚好大一点时才能进行比较,比较顺序为:A>K>Q>J>T>9>8>7>6>5>4>3。
比如:6大于5,但是不能比4大,6和4不能比较。单牌2属于特殊牌,他可以和其他所有普通单牌比较,并且是最大的。
请注意3,他不能大于任何牌。
b) 对子:即两张牌的点数相同,规则和单牌相似,也需要进行类似处理。两个2是特殊对子,可以大于所有的其他对子。
注意:对子和单牌是不能进行比较的。
c) 炸弹:3个点数相同的牌。炸弹可以大于任何单张和对子,炸弹之间的比较不用像单牌和对子那样,只能大一点才能比较。
只要满足:222>AAA>KKK>QQQ>JJJ>TTT>…>333的规则的即可。即222是最大的,AAA可以大于KKK,也可以大于333。
d) 其他规则暂不考虑实现
现在请你实现一个程序,自动判断两手牌的大小,注意:输入的牌只会出现3种类型:单张,对子,炸弹。张数最多3张。
不会出现2个单牌。比如”25”,也不会出现一个对子加单牌,比如”334”等,类似输入异常你可以不用考虑。
但是pFirstCards为单牌,pSecondCards为对子,类似的组合输入是合法的。
要求实现函数:
int CompareCards(char *pFirstCards, char *pSecondCards)
【输入】 char *pFirstCards:需要比较的第一手牌
char *pSecondCards:需要比较的第二手牌
【返回】 int 类型,返回值说明:
如果pFirstCards和 pSecondCards无法比较,比如”3”和”6”;”55”和”6”等,返回0。
如果pFirstCards大于pSecondCards,返回1。
如果pFirstCards等于 pSecondCards,返回2。
如果pFirstCards小于 pSecondCards,返回3。
注意:不用考虑输入的合法性,这个由函数的使用者保证。输入的牌均为字符’1’,’2’..’9’,大写的’A’,’T’,’J’,’Q’,’K’。
示例
输入: “77”、 “33”,返回:0
输入: “77”、 “77”,返回:2
3. 麻将胡牌(40分)
问题描述:
说起麻将,那可是川渝市民的最爱,无论亲朋好友聚会,还是业务谈判,总是少不了麻将的声音。
现实生活如此,网络上各种各样的麻将游戏也非常的多,现在游戏公司H正在做一款麻将游戏,
其中判断是否胡牌的部分希望由你来做。
成都麻将规则如下:
麻将只能包括3种类型:条,筒,万。没有“门、东南西北、红中”。每种牌都是数字从1到9,每个数字有4张,共36张,筒,万,条均一样。
胡牌规则如下:
a) 手里面的牌最多只有两种类型,即必须打缺一种,不能出现:条,筒,万都存在的情况。
b) 必须有一个对子,即两张相同的牌,比如:两个2筒,两个4条等。
c) 剩余的牌,每3张需要凑成一个有效牌,比如:3个一样的牌(3个2筒),或者3个顺子(1条2条3条),
如果所有的牌都能够凑好,再满足规则b和a,有一个对子,并且所有的牌只有两种,那么就可以胡牌了。
d) 有一种特殊牌,叫做七对,即全部的牌都是成对出现,比如:2筒2筒5筒5筒3筒3筒4条4条8条8条1条1条2条2条,
一共7对,再满足条件a,也可以胡牌。
e) 假设牌不会出现碰的情况,即手里面的牌肯定是14张。输入数据肯定都是麻将牌,不用考虑异常输入。
也不用考虑会输入“门”,“红中”等成都麻将中不会出现的牌。
要求实现函数:
bool IsMahjonggWin(char *pCards)
【输入】 char *pCards:参数说明:
假设:
条子为:T,2条输入为:2T
筒子为:D,3筒输入为:3D
万子为:W,4万输入为:4W
pCards:输入麻将序列。比如:”1T2T2T2T3T7T8T9T5D4D7D8D8D8D”
【返回】 bool类型:如果能够胡牌,返回true;如果不能胡牌,返回false。
比如:“7T1T8T2T2T2T3T9T5D4D3D8D8D8D”可以转换成“1T2T3T2T2T 7T8T9T3D4D5D8D8D8D”,可以胡牌。
注意:不用考虑输入的合法性,这个由函数的使用者保证。输入的牌为字符串,字母为大写的”TDW”,请编码的时候注意。
示例
输入: “1D2D2D2D3D3D4D4D5D5D5D6D6D7D”,返回:true
输入: “1D1D1D3D3D3D5D5D5D7D7D7D2W3W”,返回false
static int vtable[128] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
0,12,13, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, // 3
0,12,15, 0,14, 0, 0, 0, 0, 0, 9,11, 0, 0, 0, 0, // 4
0,10, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
};
// 问题1:
int CompareOneCard(char cFirstCard, char cSecondCard)
{
int a = vtable[cFirstCard];
int b = vtable[cSecondCard];
return a > b ? 1 : ( a < b ? -1 : 0);
}
// 问题2:
int CompareCards(char *pFirstCards, char *pSecondCards)
{
int n1 = strlen(pFirstCards);
int n2 = strlen(pSecondCards);
// Can't compare
if (n1 < 3 && n2 < 3 && n2 != n1)
{
return 0;
}
if (n1 > n2)
{
return 1;
}
if (n1 < n2)
{
return 3;
}
int a = vtable[*pFirstCards];
int b = vtable[*pSecondCards];
if (n1 == 3)
{
return a > b ? 1 : ( a < b ? 3 : 2);
}
else
{
if (abs(a - b) > 1 && a != 13 && b != 13)
{
return 0;
}
else
{
return a > b ? 1 : ( a < b ? 3 : 2);
}
}
return 0;
}
bool CheckMahjongg(int * table, int & c2, int &c3)
{
int pos = 0;
while (table[9] > 0)
{
if (pos >= 9)
{
pos = 0;
}
if (table[pos] == 0)
{
pos++;
continue;
}
if (pos < 7 && table[pos] == 2 && table[pos + 1] < 2)
{
c2++;
table[pos] -= 2;
table[9] -= 2;
continue;
}
if (pos < 7 && table[pos + 1] > 0 && table[pos + 2] > 0)
{
c3++;
table[pos]--;
table[pos + 1]--;
table[pos + 2]--;
table[9] -= 3;
continue;
}
if (table[pos] == 4)
{
c2 += 2;
table[pos] -= 4;
table[9] -= 4;
}
else if (table[pos] == 3)
{
c3++;
table[pos] -= 3;
table[9] -= 3;
}
else if (table[pos] == 2)
{
c2++;
table[pos] -= 2;
table[9] -= 2;
}
else if (table[pos] == 1)
{
return false;
}
}
return true;
}
// 问题3:
bool IsMahjonggWin(char *pCards)
{
int tableT[10] = {0};
int tableD[10] = {0};
int tableW[10] = {0};
int flag = 0;
char * pTmp = pCards;
for (int i = 0; i < 14; i++)
{
char s = *pTmp++;
switch (*pTmp++)
{
case 'T':
{
flag |= 1;
tableT[9]++;
tableT[s-'1']++;
}
break;
case 'D':
{
flag |= 2;
tableD[9]++;
tableD[s-'1']++;
}
break;
case 'W':
{
flag |= 4;
tableW[9]++;
tableW[s-'1']++;
}
break;
default:
break;
}
}
if (flag == 7)
{
return false;
}
int c2 = 0;
int c3 = 0;
bool bret = true;
bret = bret && CheckMahjongg(tableT, c2, c3);
bret = bret && CheckMahjongg(tableD, c2, c3);
bret = bret && CheckMahjongg(tableW, c2, c3);
if (!bret)
{
return false;
}
if (c2 != 7 && c2 != 1)
{
return false;
}
return true;
}
第三题:
#include <iostream>
using namespace std;
bool checkMahjong(char cards[], char count) {
// 检测完毕,和牌
if (count == 0) return true;
// 找到要检测的第一张牌
int current = 0;
while (!cards[current]) current++;
// 判断是否已提取过一对,并尝试提取
if (count % 3 == 2 && cards[current] >= 2) {
cards[current] -= 2;
if (checkMahjong(cards, count - 2)) return true;
cards[current] += 2;
}
// 尝试提取三个相同的牌
if (cards[current] >= 3) {
cards[current] -= 3;
if (checkMahjong(cards, count - 3)) return true;
cards[current] += 3;
}
// 尝试提取顺子
if (cards[current] >= 1 && cards[current + 1] >= 1 && cards[current + 2] >= 1) {
cards[current] -= 1; cards[current + 1] -= 1; cards[current + 2] -= 1;
if (checkMahjong(cards, count - 3)) return true;
cards[current] += 1; cards[current + 1] += 1; cards[current + 2] += 1;
}
return false;
}
bool IsMahjonggWin(char *pCards) {
// 初始化数据结构。每种类型的牌用一个0分割,这样判断顺子时就能无差别对待
char cards[29] = {0};
char cardtable[128] = {0}; cardtable['D'] = 10; cardtable['W'] = 20;
while (*pCards) {
cards[*pCards - '0' + cardtable[*(pCards + 1)]]++;
pCards += 2;
}
// 判断是否缺门。依据:统计缺门的数量
int i, j, count = 0;
for (i = 0; i < 29; i += 10) {
for (j = i; j < i + 9; j++) {
if (cards[j]) break;
}
if (j == i + 9) count++;
}
if (count == 0) return false;
// 判断是否七对。依据:数组中的值全为0、2、4
for (i = 0; i < 29; i++) {
if (cards[i] != 0 && cards[i] != 2 && cards[i] != 4) break;
}
if (i == 29) return true;
// 递归进行常规牌型判断
return checkMahjong(cards, 14);
}
int main(int argc, char* argv[])
{
cout << "Expected = 1: 1D2D2D2D3D3D4D4D5D5D5D6D6D7D = " << IsMahjonggWin("1D2D2D2D3D3D4D4D5D5D5D6D6D7D") << endl;
cout << "Expected = 0: 1D1D1D3D3D3D5D5D5D7D7D7D2W3W = " << IsMahjonggWin("1D1D1D3D3D3D5D5D5D7D7D7D2W3W") << endl;
cout << "Expected = 1: 1T1T2T2T6T6T8T8T9T9T1D1D4D4D = " << IsMahjonggWin("1T1T2T2T6T6T8T8T9T9T1D1D4D4D") << endl;
cout << "Expected = 0: 1T1T2T2T6T6T8T8T9T9T1D1D4W4W = " << IsMahjonggWin("1T1T2T2T6T6T8T8T9T9T1D1D4W4W") << endl;
getchar();
return 0;
}