如何检查数组含连续等间距数字?及扑克游戏胜负判定程序技术问询
嘿,针对你的两个问题,我来一步步给你捋清楚解决方案:
首先得明确:这里的“连续且间隔相等”其实就是数学里的等差数列对吧?比如[1,3,5](间隔2)、[10,7,4](间隔-3)都算,而[1,2,4]这种间隔不一致的就不算。
那实现思路很简单:
- 先处理边界情况:如果数组长度小于3,肯定没法形成等差数列,直接返回False。
- 把数组排序(避免原数组无序的情况,比如[5,1,3]其实是等差数列,但没排序的话直接算差值会出错)。
- 计算前两个元素的间隔,然后遍历数组,检查所有相邻元素的间隔是否和这个初始间隔一致。
给你个Python的实现例子,你可以根据自己用的语言调整:
def has_arithmetic_sequence(arr): if len(arr) < 3: return False # 先排序,统一顺序 sorted_arr = sorted(arr) # 计算初始间隔 diff = sorted_arr[1] - sorted_arr[0] # 遍历检查后续所有相邻元素的间隔 for i in range(2, len(sorted_arr)): if sorted_arr[i] - sorted_arr[i-1] != diff: return False return True
另外补充个细节:如果数组里全是重复元素(比如[2,2,2]),这个函数会返回True,因为间隔是0。如果你想排除这种情况,可以在函数里加个判断:如果diff == 0就返回False,根据你的实际需求调整就行。
你已经完成了数据拆分,拿到了双方的手牌数组和牌力数组,接下来核心就是判定每手牌的牌型等级,然后通过牌型+单张大小来分胜负。
我给你梳理下具体步骤和关键代码:
第一步:把牌力转换成可比较的数值
扑克的牌力(A、T、J这些)没法直接比大小,得转成数字。注意A比较特殊,在顺子里可以当1(比如A-2-3-4-5),也可以当14(比如10-J-Q-K-A),所以默认按14算,顺子场景单独处理:
def rank_to_value(rank): match rank: case 'A': return 14 case 'K': return 13 case 'Q': return 12 case 'J': return 11 case 'T': return 10 case _: return int(rank)
第二步:统计牌力出现次数,方便判断牌型
用计数工具统计每个牌力出现的次数,然后按“出现次数降序+牌力值降序”排序,这样能快速识别四条、葫芦这类牌型:
from collections import Counter def get_rank_counts(ranks): # ranks是转换后的数值数组,比如[14,13,12,11,10] count = Counter(ranks) # 排序后格式是[(牌力值, 出现次数), ...] return sorted(count.items(), key=lambda x: (-x[1], -x[0]))
第三步:核心牌型判定函数
扑克的牌型从高到低是:皇家同花顺 > 同花顺 > 四条 > 葫芦 > 同花 > 顺子 > 三条 > 两对 > 一对 > 高牌。我们给每个牌型分配一个等级分(越高越厉害),同时返回关键值数组(同牌型时比这个):
def evaluate_hand(ranks, suits): rank_counts = get_rank_counts(ranks) sorted_ranks = sorted(ranks, reverse=True) # 判断是否是同花:所有花色相同 is_flush = len(set(suits)) == 1 is_straight = False straight_high = 0 # 判断是否是顺子 if len(rank_counts) == 5: # 顺子必须5张不同牌 # 普通顺子:最大-最小=4 if sorted_ranks[0] - sorted_ranks[-1] == 4: is_straight = True straight_high = sorted_ranks[0] # 特殊顺子A-2-3-4-5,此时最大牌按5算 elif sorted_ranks == [14,5,4,3,2]: is_straight = True straight_high = 5 # 逐个判断牌型,返回(等级分, 关键值数组) if is_flush and is_straight: if straight_high == 14: # 皇家同花顺(10-J-Q-K-A同花) return (10, [straight_high]) else: # 同花顺 return (9, [straight_high]) elif rank_counts[0][1] == 4: # 四条:先比四条的牌力,再比剩下的单张 return (8, [rank_counts[0][0], rank_counts[1][0]]) elif rank_counts[0][1] == 3 and rank_counts[1][1] == 2: # 葫芦:先比三条的牌力,再比对子的 return (7, [rank_counts[0][0], rank_counts[1][0]]) elif is_flush: # 同花:按单张从大到小比 return (6, sorted_ranks) elif is_straight: # 顺子:比最大牌力(特殊顺子按5算) return (5, [straight_high]) elif rank_counts[0][1] == 3: # 三条:先比三条的牌力,再比剩下的单张 kickers = [x[0] for x in rank_counts[1:]] return (4, [rank_counts[0][0]] + kickers) elif rank_counts[0][1] == 2 and rank_counts[1][1] == 2: # 两对:先比大对子,再比小对子,最后比单张 return (3, [rank_counts[0][0], rank_counts[1][0], rank_counts[2][0]]) elif rank_counts[0][1] == 2: # 一对:先比对子的牌力,再比剩下的单张 kickers = [x[0] for x in rank_counts[1:]] return (2, [rank_counts[0][0]] + kickers) else: # 高牌:按单张从大到小比 return (1, sorted_ranks)
第四步:比较两手牌的胜负
拿到每手牌的(等级分, 关键值数组)后,先比等级分,等级相同就逐个比关键值:
def compare_hands(hand1_eval, hand2_eval): if hand1_eval[0] > hand2_eval[0]: return "Player One wins" elif hand1_eval[0] < hand2_eval[0]: return "Player Two wins" else: # 同等级,逐个比较关键值 for k1, k2 in zip(hand1_eval[1], hand2_eval[1]): if k1 > k2: return "Player One wins" elif k1 < k2: return "Player Two wins" # 所有关键值都相同,平局 return "Tie"
举个使用例子:如果playerOne的手牌是["AH", "KH", "QH", "JH", "TH"],转换后ranks是[14,13,12,11,10],suits是["H","H","H","H","H"],调用evaluate_hand会返回(10, [14]),也就是皇家同花顺,基本稳赢了。
内容的提问来源于stack exchange,提问作者Joshua Viggiani

