转眼发现就要期末考试了,于是最近开始重新刷一下这学期学校的oj题目,同时把一些有代表性的题目的思路整理出来,也算是巩固一些容易出错的知识吧🤭
题目
题目要求
自定义结构体表示一张扑克牌,包含类型——黑桃、红桃、梅花、方块、王;大小——2,3,4,5,6,7,8,9,10,J,Q,K,A,小王(用0表示)、大王(用1表示)。输入n,输入n张扑克牌信息,从大到小输出它们的排序结果。
假设扑克牌的排序规则是大王、小王为第一大、第二大,剩余52张扑克牌按照先花色后大小排序。
花色:黑桃>红桃>梅花>方块。
大小: A>K>Q>J>>10>9>…>2。
提示:百度sort函数、strstr函数使用。
输入
测试次数t
每组测试数据两行:
第一行:n,表示输入n张扑克牌
第二行:n张扑克牌信息,格式见样例
输出
对每组测试数据,输出从大到小的排序结果
样例输入
3
5
黑桃4 红桃10 梅花Q 方块K 黑桃A
10
大王 梅花10 红桃K 方块9 黑桃2 梅花A 方块Q 小王 黑桃8 黑桃J
5
红桃K 梅花K 黑桃K 方块K 小王
样例输出
黑桃A 黑桃4 红桃10 梅花Q 方块K
大王 小王 黑桃J 黑桃8 黑桃2 红桃K 梅花A 梅花10 方块Q 方块9
小王 黑桃K 红桃K 梅花K 方块K
整体思路
- 这一题涉及到的知识点为对于结构体的排序,以及如何表示扑克牌的大小。
- 可以看到扑克牌中除了大小王,其他牌面都能由花色跟数字构成,因此我们可以通过构建两个数组,即花色数组和数字数组来决定一张牌的大小,如下所示:
- 可以看到在数字数组中,我们按照的是从小到大的顺序进行构建,比如下标为0的元素为2,下标为12的元素为A,因此可以通过下标的大小来判断数字的大小。
- 同理,花色数组中按照从大到小的顺序进行排序,下标为0的“大王”是最大的,下标为5的“方块”是最小的,因此可以通过下标来判断花色的大小。
string number_rule[13] = { "2","3","4","5","6","7","8","9","10","J","Q","K","A" };
string flower[6] = { "大王","小王","黑桃","红桃","梅花","方块" };
- 综上所述,我们的扑克牌结构体应当包含三个元素:扑克牌的名字,花色对应花色数组的下标,数字对应数字数组的下标:
struct Poke {
string name;
int number;
int flower;
};
- 对于若干张扑克牌的排序,我们可以通过自定义排序规则的方式结合sort函数使用,如下:
bool cmp(Poke A, Poke B) {
if (A.flower != B.flower) //先比较花色大小,下标越小则表示花色越大
return A.flower < B.flower;
else //若花色相同,则比较数字下标,下标越大表示数字的值越大
return A.number > B.number;
}
- 最后一个要点是我们需要从扑克牌的名字中去找到该牌面的花色下标是多少和数字下标是多少。这题中我使用的是string表示扑克牌的名字,因此可以用string中的find函数判断是否含有子串进而决定花色和数字的下标,如下所示:
string number_rule[13] = { "2","3","4","5","6","7","8","9","10","J","Q","K","A" };
string flower[6] = { "大王","小王","黑桃","红桃","梅花","方块" };
//判断A中的数字对应数字数组number_rule的下标是多少
int judge_number(string A) {
for (int i = 0; i < 13; i++) {
//表示A中含有里面的字串
if(A.find(number_rule[i]) != string::npos) //若A找不到子串number_rule[i],则会返回string::npos!!!
return i; //返回A中的数字在数字数组number_rule的下标
}
return -1; //若都找不到则返回-1,如大小王
}
//判断A中的花色对应花色数组flower的下标是多少
int judge_flower(string A) {
for (int i = 0; i < 6; i++) {
if (A.find(flower[i]) != string::npos)
return i; //返回A中的花色在花色数组number_rule的下标
}
return -1;
}
完整代码
#include <iostream>
#include <algorithm>
#include <iomanip>
#include<string>
using namespace std;
string number_rule[13] = { "2","3","4","5","6","7","8","9","10","J","Q","K","A" };
string flower[6] = { "大王","小王","黑桃","红桃","梅花","方块" };
//扑克牌结构体
struct Poke {
string name;
int number;
int flower;
};
//判断A中的数字对应数字数组number_rule的下标是多少
int judge_number(string A) {
for (int i = 0; i < 13; i++) {
//表示A中含有里面的字串
if(A.find(number_rule[i]) != string::npos)
return i;
}
return -1;
}
//判断A中的花色对应花色数组flower的下标是多少
int judge_flower(string A) {
for (int i = 0; i < 6; i++) {
if (A.find(flower[i]) != string::npos)
return i;
}
return -1;
}
//两张扑克牌的排序比较规则,用于sort函数
bool cmp(Poke A, Poke B) {
if (A.flower != B.flower)
return A.flower < B.flower;
else
return A.number > B.number;
}
int main()
{
int t;
cin >> t; //测试案例个数
while (t--) {
int n;
cin >> n; //该组案例的扑克牌张数
Poke *A = new Poke[n];
for (int i = 0; i < n; i++) {
cin >> A[i].name; //输入该张牌的名字
A[i].number = judge_number(A[i].name);//得到该牌的数字对应的下标
A[i].flower = judge_flower(A[i].name);//得到该牌的花色对应的下标
}
sort(A, A + n, cmp); //从大到小进行排序
for (int i = 0; i < n; i++) { //进行该组测试的输出
if (i != n - 1)
cout << A[i].name << " ";
else
cout << A[i].name << endl;
}
}
return 0;
}