问题说明
扑克牌所有的面值有’A’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’,‘10’,‘J’,‘Q’,‘K’,‘Joker’,拍序的规则是四个的放一起,三个的放一起,对子放一起,个子放一起,无论是四个、三个、对子还是个子,内部都需按大到小排序,并且先排四个,再排三个,再排对子,再排个子。
问题分析
1、按不同的游戏规则,‘A’在所有面值中的大小是不固定的,可能比‘K’大,也可能按‘1’算,成为最小的。其它一般都会是正常顺序。
2、作为程序,在输入时只可能作为字符串来输入,这时像‘10’,‘Joker’,都是占多个字符的,想对它们进行排序,须先将多个字符取出,转换为单个字符再进行排序才能方便。如果全面值排序,个人觉得将面值都转换成整型存入数组或vector里,再进行排序会比较方便。str[0]-‘0’可将字符数字转化为整型数字,其它字母switch…case…转换吧。如果条件只是数字,或带个’A’,没有花牌参与,字符型字母在ASCII表里比字符型数字要大,则可将’A’转化为’1’再进行排,大大降低复杂度。
3、遍历遇到’1‘时,后面肯定是’0‘,只需将其转化为10,遇到’J’时,则需看后方是不是’o’来判断是’J’还是’Joker’。
简化及代码
这里只列数字及’A’的排序,只有个子及对子,个子及对子内部按由大到小排序,输出时先对子再个子的顺序。其它情况相似方法进行扩展。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string cards;
string douExp;
unsigned int strlen;
cout<< "Plsease input five card number: ";
getline (std::cin, cards);
cout<<"Input: "<<cards<<endl;
strlen=cards.size();
for(auto &C:cards)
if(C == 'A')
C = '1';
cout<<"real num:"<<cards<<endl;
//下方双循环适用于非全对子,最起码有张个子。如果牌数为奇数则可放心使用
for(unsigned int i=0; i<strlen; i++)
{
for(unsigned int j=i+1; j<strlen; j++)
{
if(cards[i] == cards[j]) //如果发现有相同的字符,本串移除此字符,它处处理
{
if(douExp.empty() || cards[i] < douExp[0])
douExp.push_back(cards[i]);
else
{
douExp[1] = douExp[0];
douExp[0] = cards[i];
}
//本串移除此字符
cards.erase(cards.begin()+j);
cards.erase(cards.begin()+i);
strlen = strlen -2;
i = 0;
j = 0;
}
if(cards[i] < cards[j]) //本串正常排序
{
char temp;
temp = cards[j];
cards[j] = cards[i];
cards[i] = temp;
}
}
}
cout<<endl;
for(auto &C:cards)
if(C == '1')
C = 'A';
cout<<"Output: ";
if(douExp.size() > 0)
{
for(unsigned int i=0; i<douExp.size(); i++)
{
if(douExp[i] == '1')
cout<<'A'<<'A';
else
cout<<douExp[i]<<douExp[i];
}
}
cout<<cards<<endl;
system("pause");
return 0;
}
此类题看似不难,但具体要考虑的细节确很多,对于思维严密的大神不敢说,但一般人肯定是要调试几遍的。