最近又做了一个新的德州扑克算法,和之前的还略有不同,
之前的德州扑克算法规则为:玩家手中的两张私有牌必须参与到牌型组合中去,
也就是公共牌最多选择3张,这次做的又不一样了:限度放宽,可以5张牌全部来自于公共牌,
换个角度,也就是从2张私有牌和5张公共牌组合成的7张牌中选择一个最优解.
解法分析
最简单的解法自然是穷举,但是逻辑也很恶心,而且运算量也比较大,PASS掉。
我想到的一种抽丝拨茧的方法是:
- 对卡组进行降序排序
- 遍历卡组,记录如下特征:最长顺子长度以及起始值、
3张相同牌的集合、2张相同牌的集合、4张相同牌的值、牌的类型数目 - 接下来就是判断过程了
- 判断是否有4张相同的牌,如果有,那么在剩下的牌中选张最大的组成四条
- 如果可以同花色,且最长顺子长度大于4,判断是否可以组成(皇家)同花顺
- 如果有3张相同的牌, 而且同时存在另外一套3张相同的牌或者存在2张相同的牌,
那么牌型是葫芦 - 如果可以同花色,那么牌型是同花
- 如果最大顺子长度大于4,那么可以是顺子
- 如果存在3张相同的牌,再找两张大牌组成三条
- 如果有多组2张相同的牌,那么再找一张最大牌组成两对
- 如果只有一组2张相同的牌,那么再找3张最大的牌组成对子
- 最后就只可能是高牌了
示例代码
class TaxasPlayerV2(object): def __init__(self, cds): self.cards = cds self.cards.sort(cmp=GameBase.get_card_cmp_func(1), reverse=True) def find_best_solution(self): max_seq_num = 1 seq_start_val = self.cards[0].value pre = None # pairs 和 thirds 存的是该对子或三张的牌值 pairs = [] thirds = [] four = None same_count = 1 card_types = [[], [], [], [], []] for card in self.cards: val = card.value card_types[card.type].append(val) if pre: if pre == val: # 对子情况 same_count += 1 if same_count == 2: pairs.append(val) elif same_count == 3: pairs.pop() thirds.append(val) elif same_count == 4: four = val break else: # 与前面一张牌值不同 same_count = 1 if max_seq_num < 5: # 没有组成序列 diff = pre - val if diff == 1 or diff == -12: # 顺子情况, 3 -> 2 or A -> k max_seq_num += 1 else: # 无法构成序列时重置数据 seq_start_val = val max_seq_num = 1 pre = val if four: # 找到最大的单牌 for item in self.cards: if item.value != four: return TaxasSolution(ResultType.Four, (four, item.value)) same_color = None for card_list in card_types: if len(card_list) > 4: same_color = card_list break # same_color = [card1, card2, ...] if same_color and max_seq_num > 4: # 判断是否是同花, 相同颜色的已经排好队在same_color中了 idx = 1 ng_count = 0 header = pre = same_color[0] if same_color[0] > 1 else 14 while idx < len(same_color): val = same_color[idx] if same_color[idx] > 1 else 14 if pre - val == 1: ng_count += 1 else: ng_count = 1 header = val if ng_count == 4: break idx += 1 pre = val if ng_count >= 4: return TaxasSolution(ResultType.RoyalFlush if header == 14 else ResultType.Flush, (header,)) if thirds: if len(thirds) == 2: return TaxasSolution(ResultType.Gourd, (thirds[0], thirds[1])) if pairs: return TaxasSolution(ResultType.Gourd, (thirds[0], pairs[0])) if same_color: return TaxasSolution(ResultType.SameColor, same_color[:5]) if max_seq_num > 4: return TaxasSolution(ResultType.Sequence, (seq_start_val,)) if thirds: thirds_val = thirds[0] flag = [thirds_val] for item in self.cards: if item.value != thirds_val: flag.append(item.value) if len(flag) == 3: break # 再找两个散牌 return TaxasSolution(ResultType.Three, flag) if len(pairs) > 1: pair_tag = [pairs[0], pairs[1]] for item in self.cards: val = item.value if val not in pair_tag: pair_tag.append(val) break # 使用前两对, 再找一个大散牌 return TaxasSolution(ResultType.TwoPair, pair_tag) elif len(pairs) == 1: pair_tag = [pairs[0]] for item in self.cards: val = item.value if val != pairs[0]: pair_tag.append(val) if len(pair_tag) == 4: break return TaxasSolution(ResultType.SinglePair, pair_tag) return TaxasSolution(ResultType.HighCard, [self.cards[i].value for i in range(0, 5)])