扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A,2各4张,小王1张,大王1张。牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):)
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER 输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如:4 4 4 4-joker JOKER 请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR基本规则:
(1)输入每手牌可能是个子,对子,顺子(连续5张),三个,炸弹(四个)和对王中的一种,不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列; (2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子) (3)大小规则跟大家平时了解的常见规则相同,个子,对子,三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌; (4)输入的两手牌不会出现相等的情况。答案提示:
(1)除了炸弹和对王之外,其他必须同类型比较。 (2)输入已经保证合法性,不用检查输入是否是合法的牌。 (3)输入的顺子已经经过从小到大排序,因此不用再排序了.输入描述:
输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如4 4 4 4-joker JOKER。输出描述:
输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR。输入例子1:
4 4 4 4-joker JOKER输出例子1:
joker JOKER1.思考
(1) 看到这道题的第一反应就是很有意思!然后直观感觉就是比较简单!虽然其基本思路就是“比较”,但是后来进行处理和操作的过程真的是十分繁琐啊;
(2) 处理比较繁琐的原因有以下几点:
- 为了能够重复输入不同的测试数据,则要用到while函数;因为输入的数据是不定长的,并以回车为中止,所以考虑用getline();但用了getline()之后就要考虑将前后两手牌分开,这里的思路是这样的: (a) 先将输入的字符串input以“-”为分界分为两手牌;(这里要注意'-'是字符,"-"是字符串,特别是在比较大小的时候要统一) (b) 再写一个函数BreakSpace来将每手牌以空格为界线分开,从而将两手牌放入vector <string>中。
- 然后是比较大小,有以下几点: (a) 由题意可知“输入每手牌可能是个子,对子,顺子(连续5张),三个,炸弹(四个)和对王中的一种,不存在其他情况”,归纳总结可以知道在两手牌数目相同的情况下,两者都是比较最小牌的大小的,因此只要拿出poker1[0]和poker2[0]进行大小比较就好; (b) 即使是单牌的比较大小,扑克的规则也是不一样的,至少不能通过ASCII码进行比较。因此,这里通过ConstructMap来构建了一个unordered_map来规定每张牌的大小,从而进行比较; (c) 在a、b两点中都是牌数相同情况下的比较大小,事实上还存在牌数不同的情况,因此在Compare()中列举了几种情况:其中一人是2张牌,且为大小王;其中一人是4张牌,且为炸弹; (d) 除此之外的其他情况都是不能比较大小的。
- 规定poker1大于poker2的时候返回1,小于则返回2,不能比较大小则返回3。
- 自己这个思路很简单粗暴,还要再思考!
- 另附牛客网评论里的思路,太简单漂亮了!
2.知识点
- string中的find()、substr();
- endl相当于是回车,在要输出多组结果的时候要特别注意。
3.实现
#include#include #include #include #include using namespace std;unordered_map mp;void ConstructMap(){ //ASCII code: 3-9:51-57, J-90, Q-97, K-91, A-81 mp["3"] = 1; mp["4"] = 2; mp["5"] = 3; mp["6"] = 4; mp["7"] = 5; mp["8"] = 6; mp["9"] = 7; mp["10"] = 8; mp["J"] = 9; mp["Q"] = 10; mp["K"] = 11; mp["A"] = 12; mp["2"] = 13; mp["joker"] = 14; mp["JOKER"] = 15;}void BreakSpace(string s, vector & p){ int pos; while (1){ pos = s.find(" "); if (pos>0){ p.push_back(s.substr(0,pos)); s = s.substr(pos + 1); } else{ p.push_back(s); break; } }}bool Cmp(string a, string b){ return mp[a] > mp[b];}int Compare(vector a, vector b){ int la= a.size(), lb = b.size(); if (la == lb){//The same size, and the same type. if (Cmp(a[0], b[0])) return 1; else return 2; } else{//Different size. //Special case if (la == 2){//joker+JOKER if (a[0] == "joker" && a[1] == "JOKER") return 1; } else if (lb == 2){//joker+JOKER if (b[0] == "joker" && b[1] == "JOKER") return 2; } if (la == 4){//same pokers if (a[0] == a[1] && a[0] == a[2] && a[0] == a[3]){ return 1; } } else if (lb == 4){//same pokers if (b[0] == b[1] && b[0] == b[2] && b[0] == b[3]){ return 2; } } } return 3;}int main(){ vector poker1, poker2, poker; string input; bool flag = false; while (getline(cin, input)){ poker1.clear(); poker2.clear(); //Construct vector flag = false; auto pos = input.find("-"); string str1 = input.substr(0, pos); string str2 = input.substr(pos+1); BreakSpace(str1, poker1); BreakSpace(str2, poker2); //Compare ConstructMap(); int res = Compare(poker1, poker2); poker = res <= 1 ? poker1 : poker2; if (res == 3){ cout << "ERROR" << endl; } else{ auto len = poker.size(); for (int i = 0; i < len; i++){ if (i < len - 1){ cout << poker[i] << " "; } else{ cout << poker[i] << endl; } } } } return 0;}//REF//“输入每手牌可能是个子,对子,顺子(连续5张),三个,炸弹(四个)和对王中的一种,//不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列“//这句规则让牌面类型的确定和大小的比较直接可以转换为牌个数的比较了,这是解决测试问题的捷径!//所以一定要善于利用题目已知条件!!!#include #include #include using namespace std;int main(){ string line; while(getline(cin,line)){ if(line.find("joker JOKER")!=-1) cout<<"joker JOKER"< str.find(first2)) cout< <