Python克里比奇牌得分计算问题:长度为3的双顺子重复值未存储
克里比奇顺子得分函数:长度3双顺子无法正确统计的问题修复
我编写的count_runs函数能正确统计多数克里比奇顺子得分,但长度为3的双顺子(因存在对子导致多个3张顺子的情况)例外——当这类顺子出现在其他顺子之后时,重复值无法被正确保留到duplicate_values列表,导致得分计算错误。其他顺子类型均正常运行。
原代码:
def count_runs(card_values): all_values = [] duplicate_values = [] for i, value in enumerate(card_values): if value in all_values: if value not in duplicate_values: duplicate_count = card_values.count(value) if duplicate_count == 2: duplicate_values.append(value) elif duplicate_count == 3: duplicate_values += [value, value] else: all_values.append(value) all_values.sort() run_points = 0 run_length = 1 for i in range(1, len(all_values)): if all_values[i] == all_values[i-1]: continue if all_values[i] == all_values[i-1] + 1: run_length += 1 else: if run_length >= 3: if len(duplicate_values) == 1 and duplicate_values[0] in range(all_values[i-run_length], all_values[i-1]+1): run_points += run_length * 2 elif len(duplicate_values) == 2: if duplicate_values[0] == duplicate_values[1] and duplicate_values[0] in range(all_values[i-run_length], all_values[i-1]+1): run_points += run_length * 3 elif duplicate_values[0] != duplicate_values[1] and all(x in range(all_values[i-run_length], all_values[i-1]+1) for x in duplicate_values): run_points += run_length * 4 else: run_points += run_length else: run_points += run_length run_length = 1 duplicate_values = [] if run_length >= 3: if len(duplicate_values) == 1 and duplicate_values[0] in range(all_values[-run_length], all_values[-1]+1): run_points += run_length * 2 elif len(duplicate_values) == 2: if duplicate_values[0] == duplicate_values[1] and duplicate_values[0] in range(all_values[-run_length], all_values[-1]+1): run_points += run_length * 3 elif duplicate_values[0] != duplicate_values[1] and all(x in range(all_values[-run_length], all_values[-1]+1) for x in duplicate_values): run_points += run_length * 4 else: run_points += run_length else: run_points += run_length print("Duplicate Values: ", duplicate_values) return run_points
问题原因分析
全局重复值收集导致跨run污染:
duplicate_values是全局收集所有牌的重复值,而非针对当前处理的顺子(run)。当存在多个顺子时,某个顺子的得分计算会包含其他顺子的重复值,导致判断错误。run结束后清空重复值列表:
在处理完一个顺子后,代码执行duplicate_values = []清空列表,导致后续顺子无法使用原本收集到的重复值。比如当长度3的双顺子出现在第二个位置时,处理第一个顺子后列表被清空,后续无法识别该双顺子的重复值。
修复方案
改用频率字典预处理所有牌的出现次数,然后针对每个顺子单独统计其范围内的重复情况,避免全局状态干扰:
from collections import Counter def count_runs(card_values): # 预处理所有值的出现频率 value_counts = Counter(card_values) # 获取去重并排序后的值 sorted_unique = sorted(value_counts.keys()) run_points = 0 n = len(sorted_unique) i = 0 while i < n: # 找到当前连续顺子的结束位置 end = i while end + 1 < n and sorted_unique[end + 1] == sorted_unique[end] + 1: end += 1 run_length = end - i + 1 if run_length >= 3: # 统计当前顺子范围内的重复值情况 duplicates = [] for val in sorted_unique[i:end+1]: cnt = value_counts[val] if cnt >= 2: # 每多一个重复,就多一个乘数因子(比如3张同牌贡献2个额外因子) duplicates.extend([val] * (cnt - 1)) # 计算当前顺子的得分乘数:1 + 重复值的数量 multiplier = 1 + len(duplicates) run_points += run_length * multiplier # 跳到下一个非连续的位置 i = end + 1 return run_points
修复说明
- 频率字典预处理:用
Counter统计每个牌值的出现次数,避免多次调用count()导致的性能问题。 - 独立处理每个顺子:遍历排序后的唯一值,找到每个连续顺子的范围,单独统计该范围内的重复值数量。
- 动态计算乘数:每个重复值(超过1次的部分)会增加顺子的组合数,比如对子贡献1个额外乘数(总乘数2),三张同牌贡献2个额外乘数(总乘数3),两个不同对子贡献2个额外乘数(总乘数4),完全符合克里比奇的得分规则。
测试用例验证:
- 输入
[2,2,3,4](长度3的双顺子):返回3*2=6,正确。 - 输入
[6,7,8,2,2,3,4](两个顺子,第二个是双顺子):返回3 + 3*2=9,正确。 - 输入
[2,2,3,3,4](两个对子的3张顺子):返回3*4=12,正确。
内容的提问来源于stack exchange,提问作者ajhansn2
相关产品推荐
相关产品推荐

