【华为OD-E卷 - 德州扑克 100分(python、java、c++、js、c)】
【华为OD-E卷 - 德州扑克 100分(python、java、c++、js、c)】
题目
五张牌,每张牌由牌大小和花色组成,牌大小2~10、J、Q、K、A,牌花色为红桃、黑桃、梅花、方块四种花色之一。
判断牌型:
牌型1,同花顺:同一花色的顺子,如红桃2红桃3红桃4红桃5红桃6。 牌型2,四条:四张相同数字 + 单张,如红桃A黑桃A梅花A方块A + 黑桃K。 牌型3,葫芦:三张相同数字 + 一对,如红桃5黑桃5梅花5 + 方块9梅花9。 牌型4,同花:同一花色,如方块3方块7方块10方块J方块Q。 牌型5,顺子:花色不一样的顺子,如红桃2黑桃3红桃4红桃5方块6。 牌型6,三条:三张相同+两张单。
说明:
(1)五张牌里不会出现牌大小和花色完全相同的牌。 (2)编号小的牌型较大,如同花顺比四条大,依次类推。 (3)包含A的合法的顺子只有10 J Q K A和A 2 3 4 5;类似K A 2 3 4的序列不认为是顺子
输入描述
- 输入由5行组成,每行为一张牌大小和花色,牌大小为2~10、J、Q、K、A,花色分别用字符H、S、C、D表示红桃、黑桃、梅花、方块
输出描述
- 输出牌型序号,5张牌符合多种牌型时,取最大的牌型序号输出
用例
用例一:
输入:
4 H
5 S
6 C
7 D
8 D
输出:
5
用例二:
输入:
9 S
5 S
6 S
7 S
8 S
输出:
1
python解法
- 解题思路:
- 这道题目要求判断给定的五张牌组合是什么类型的牌型,并返回相应的数字编码。我们要根据标准的扑克牌规则来判断牌型。常见的牌型包括顺子(Shunzi)、同花(Tonghua)、三条(Santiao)、葫芦(Hulu)、四条(Sitiao)等。
解题的步骤如下:
输入处理:
我们需要读取五张牌的输入,每张牌由数字和花色组成。输入后将其转换成一个二维列表,方便后续处理。
牌值转换:
将牌的数字(包括 J, Q, K, A 等)转换成数值,以便进行大小比较。
例如:J 转换为 11,Q 转换为 12,K 转换为 13,A 转换为 14。
牌型判断:
顺子(Shunzi):五张牌是连续的。
同花(Tonghua):五张牌的花色相同。
三条(Santiao):有三张相同的牌。
葫芦(Hulu):有三张相同的牌和两张相同的牌。
四条(Sitiao):有四张相同的牌。
返回结果:
根据判断的结果返回相应的牌型编号。例如:顺子同花返回 1,四条返回 2,葫芦返回 3,等等。
# 获取五张牌的输入,输入格式:每行一个数字和花色,格式如 "3 H"
arr = [input().split() for _ in range(5)]
# 将牌面值转换为相应的数字值,方便后续比较
def cards(num):
if num == "J":
return 11
elif num == "Q":
return 12
elif num == "K":
return 13
elif num == "A":
return 14
else:
return int(num)
# 用于判断一组牌是否满足特定条件:
# partCount:分成几组相同的牌
# maxSameNumCount:每组最多相同的牌的数量
def countNums(nums, partCount, maxSameNumCount):
count = {}
# 统计每种牌的数量
for num in nums:
if count.get(num) is None:
count[num] = 0
count[num] += 1
# 判断是否有 partCount 种牌
if len(count.keys()) != partCount:
return False
# 判断是否有 maxSameNumCount 个相同的牌
return maxSameNumCount in count.values()
# 判断是否是三条:有三张相同的牌
def isSantiao(nums):
return countNums(nums, 3, 3)
# 判断是否是葫芦:有三张相同的牌和两张相同的牌
def isHulu(nums):
return countNums(nums, 2, 3)
# 判断是否是四条:有四张相同的牌
def isSitiao(nums):
return countNums(nums, 2, 4)
# 判断是否是同花:五张牌的花色相同
def isTonghua(colors):
return len(set(colors)) == 1
# 判断是否是顺子:五张牌是连续的
def isShunzi(nums):
# 特殊情况:2345A,A作为1处理
if "".join(nums) == "2345A":
return True
# 判断牌是否连续
for i in range(1, len(nums)):
if cards(nums[i - 1]) + 1 != cards(nums[i]):
return False
return True
# 获取最终结果的函数
def getResult():
nums = []
colors = []
# 分离出牌面数字和花色
for num, color in arr:
nums.append(num)
colors.append(color)
# 对牌面值进行排序
nums.sort(key=lambda x: cards(x))
# 判断各种牌型的优先级
if isShunzi(nums) and isTonghua(colors): # 同花顺
return 1
elif isSitiao(nums): # 四条
return 2
elif isHulu(nums): # 葫芦
return 3
elif isTonghua(colors): # 同花
return 4
elif isShunzi(nums): # 顺子
return 5
elif isSantiao(nums): # 三条
return 6
else: # 其他情况
return 0
# 输出最终的牌型编号
print(getResult())
java解法
- 解题思路
- 这道题目要求根据输入的五张牌的点数和花色,判断其牌型并返回对应的编码。常见的牌型有同花顺、四条、葫芦、同花、顺子、三条等。
解题步骤如下:
输入获取:
从输入中获取五张牌的点数(数字或字母)和花色。每张牌由一个数字(或字母表示的特殊牌,如 J, Q, K, A)和一个花色组成。
牌值转换:
将牌面上的字符(例如 J, Q, K, A)转换为数字值,方便后续排序和比较。
J 转换为 11
Q 转换为 12
K 转换为 13
A 转换为 14
数字牌保持不变。
分析牌型:
同花顺(Straight Flush):五张牌是连续的,并且花色相同。
四条(Four of a Kind):有四张相同的牌。
葫芦(Full House):有三张相同的牌和两张相同的牌。
同花(Flush):五张牌的花色相同。
顺子(Straight):五张牌是连续的,不考虑花色。
三条(Three of a Kind):有三张相同的牌。
返回结果:
根据不同的牌型,返回对应的数字编码。例如:同花顺返回 1,四条返回 2,葫芦返回 3,等等。如果不符合任何牌型,返回 0。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] nums = new String[5]; // 存储五张牌的点数
String[] suits = new String[5]; // 存储五张牌的花色
// 输入五张牌的点数和花色
for (int i = 0; i < 5; i++) {
nums[i] = sc.next(); // 输入点数
suits[i] = sc.next(); // 输入花色
}
// 输出牌型结果
System.out.println(getResult(nums, suits));
}
// 根据牌的点数和花色来判断牌型
public static int getResult(String[] nums, String[] suits) {
// 使用 TreeSet 存储牌的数值,保证自动排序
TreeSet<Integer> values = new TreeSet<>();
// 使用 Map 存储每个点数的出现次数
Map<String, Integer> count = new HashMap<>();
// 使用 Set 存储花色,判断是否同花
Set<String> suitSet = new HashSet<>(Arrays.asList(suits));
// 遍历所有牌,转换成数值并统计点数出现次数
for (String num : nums) {
int cardVal = cardValue(num); // 将牌的点数转换为数值
values.add(cardVal); // 将牌数值加入到 TreeSet,自动排序
count.put(num, count.getOrDefault(num, 0) + 1); // 更新点数出现次数
}
// 判断是否是同花:如果所有花色相同,则为同花
boolean isFlush = suitSet.size() == 1;
// 判断是否是顺子:如果牌的最大值与最小值差为 4 且牌数为 5,则为顺子
// 或者特殊情况:A, 2, 3, 4, 5 也是顺子
boolean isStraight = (values.last() - values.first() == 4 && values.size() == 5) || isLowAceStraight(values);
// 牌型判断,从高到低:
if (isStraight && isFlush) return 1; // 同花顺
if (hasCount(count, 4)) return 2; // 四条
if (hasCount(count, 3) && hasCount(count, 2)) return 3; // 葫芦
if (isFlush) return 4; // 同花
if (isStraight) return 5; // 顺子
if (hasCount(count, 3)) return 6; // 三条
return 0; // 没有符合的牌型
}
// 判断是否有某个点数出现 num 次
private static boolean hasCount(Map<String, Integer> count, int num) {
return count.containsValue(num);
}
// 判断是否是 A 2345 这种顺子(特殊情况)
private static boolean isLowAceStraight(TreeSet<Integer> values) {
return values.contains(14) && values.contains(2) && values.contains(3) && values.contains(4) && values.contains(5);
}
// 将牌的点数转换为数值
private static int cardValue(String num) {
switch (num) {
case "J": return 11; // Jack
case "Q": return 12; // Queen
case "K": return 13; // King
case "A": return 14; // Ace
default: return Integer.parseInt(num); // 其他牌是数字,直接返回数字
}
}
}
C++解法
- 解题思路
更新中
C解法
更新中
JS解法
更新中
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏