- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
关闭。这个问题需要更多 focused .它目前不接受答案。
想改进这个问题?更新问题,使其仅关注一个问题 editing this post .
3个月前关闭。
Improve this question
首先声明一下:我是一名医疗专业人士,业余爱好 Python 和扑克。我没有接受过这些方面的正式培训,也不知道计算机科学类(class)的类(class)内容。
我使用的计算机是台式机 i7-4790 3.6 Ghz,具有 16 GB RAM 和 Jupyter Notebooks。
我的目标是编写相当于 pokerstrategy.com Equilab 或 https://www.cardschat.com/poker-odds-calculator.php 的代码为了我。我只会坚持德州扑克。
为此,我需要为任何 5 张牌组合编写一个评估器。我这样做了,它完美地完成了这项工作,考虑了手中的每张牌并产生一个元组作为输出,例如:
('2h', '3c', '4s', '6s', 'Jh'): (0, 11, 6, 4, 3, 2)
High-card hand, kickers J, 6, 4, 3, 2
('7c', 'Ad', 'Kd', 'Kh', 'Tc'): (1, 13, 14, 10, 7)
One pair, pair of kings, kickers A, T, 7
('2c', '3c', '4c', '5c', 'Ac'): (8, 5)
Straight flush, 5 high
import collections
import random
import itertools
import timeit
import time
ranks = ['2','3','4','5','6','7','8','9','T','J','Q','K','A']
names ="Deuces Threes Fours Fives Sixes Sevens Eights Nines Tens Jacks Queens Kings Aces"
cardnames = names.split()
cardnames
suitsall = "hearts spades diamonds clubs"
suitnames = suitsall.split()
suitnames
suits = ['h','s','d','c']
cards = []
# Create all cards from suits and ranks
for suit in suits:
for rank in ranks:
cards.append(rank + suit)
# Create all possible flops by chosing 3 cards out of a deck
flops = list(itertools.combinations(cards, 3))
# Create all possible boards by chosing 5 cards out of a deck
boards = list(itertools.combinations(cards, 5))
# Create all possible starting hands
startingHands = list(itertools.combinations(cards, 2))
# Function dict_hand_rank ranks every board and returns a tuple (board) (value)
def hand_rank_dict(hand):
suits = []
ranks_alphabetical = []
ranks_numerical = []
ranks_histogram = []
kickers = []
kickers_text = []
isFlush = False
isStraight = False
isStraightFlush = False
handrankValue = 0
straightHeight = -1
straightName = "No straight"
handName = "none yet"
for card in hand:
suits.append(card[1])
ranks_alphabetical.append(card[0])
# create ranks_histogram where from A 2 ... J Q K A every card has the corresponding number of occurencies, A double counted
ranks_histogram.append(str(ranks_alphabetical.count('A')))
for rank in ranks:
ranks_histogram.append(str(ranks_alphabetical.count(rank)))
joined_histogram = ''.join(ranks_histogram)
# create ranks numerical instead of T, J, Q, K A
for card in hand:
ranks_numerical.append(ranks.index(card[0])+2)
# create kickers
kickers = sorted([x for x in ranks_numerical if ranks_numerical.count(x) <2], reverse = True)
# check if a hand is a straight
if '11111' in joined_histogram:
isStraight = True
straightHeight = joined_histogram.find('11111') + 5
straightName = cardnames[straightHeight - 2]
handName = "Straight"
handrankValue = (4,) + (straightHeight,)
# check if a hand is a flush
if all(x == suits[0] for x in suits):
isFlush = True
handName = "Flush " + cardnames[kickers[0] - 2] + " " + cardnames[kickers[1] - 2] \
+ " " + cardnames[kickers[2] - 2] + " " + cardnames[kickers[3] - 2] + " " + cardnames[kickers[4] - 2]
handrankValue = (5,) + tuple(kickers)
# check if a hand is a straight and a flush
if isFlush & isStraight:
isStraightFlush = True
handName = "Straight Flush"
handrankValue = (8,) + (straightHeight,)
# check if a hand is four of a kind
if '4' in joined_histogram:
fourofakindcard = (joined_histogram[1:].find('4') + 2)
handName = "Four of a Kind " + cardnames[fourofakindcard -2] + " " + cardnames[kickers[0] - 2] + " kicker"
handrankValue = (7,) + ((joined_histogram[1:].find('4') + 2),) + tuple(kickers)
# check if a hand is a full house
if ('3' in joined_histogram) & ('2' in joined_histogram):
handName = "Full house"
handrankValue = (6,) + ((joined_histogram[1:].find('3') + 2),) + ((joined_histogram[1:].find('2') + 2),) + tuple(kickers)
# check if a hand is three of a kind
if ('3' in joined_histogram) & (len(kickers) == 2):
threeofakindcard = (joined_histogram[1:].find('3') + 2)
handName = "Three of a Kind " + cardnames[threeofakindcard -2] + " " + cardnames[kickers[0] - 2] + \
" " + cardnames[kickers[1] - 2]
handrankValue = (3,) + ((joined_histogram[1:].find('3') + 2),) + tuple(kickers)
# check if a hand is two pairs
if ('2' in joined_histogram) & (len(kickers) == 1):
lowerpair = (joined_histogram[1:].find('2') + 2)
higherpair = (joined_histogram[lowerpair:].find('2') + 1 + lowerpair)
handName = "Two pair " + cardnames[higherpair -2] + " and " + cardnames[lowerpair - 2] + " " + \
cardnames[kickers[0] - 2] + " kicker"
handrankValue = (2,) + (higherpair, lowerpair) + tuple(kickers)
# check if a hand is one pair
if ('2' in joined_histogram) & (len(kickers) == 3):
lowerpair = (joined_histogram[1:].find('2') + 2)
handName = "One pair " + cardnames[lowerpair - 2] + " kickers " + cardnames[kickers[0] - 2] \
+ " " + cardnames[kickers[1] - 2] + " " + cardnames[kickers[2] - 2]
handrankValue = (1,) + (lowerpair,) + tuple(kickers)
# evaluate high card hand
if (len(ranks_numerical) == len(set(ranks_numerical))) & (isStraight == False) & (isFlush == False):
handName = "High card " + cardnames[kickers[0] - 2] + " " + cardnames[kickers[1] - 2] \
+ " " + cardnames[kickers[2] - 2] + " " + cardnames[kickers[3] - 2] + " " + cardnames[kickers[4] - 2]
handrankValue = (0,) + tuple(kickers)
return {tuple(sorted(hand)) : handrankValue}
ranked_hands_dict = {}
t0 = time.time()
for board in boards:
ranked_hands_dict.update(hand_rank_dict(board))
t1 = time.time()
total = t1-t0
# print(total)
# Function that given board and 2 cards gives back tuple of the best possible hand by searching through ranked_hands_dict keys
def find_the_best_hand(board, card1, card2):
seven_card_hand = board + (card1,) + (card2,)
evaluated_all_possible_hands = []
if (card1 in board) or (card2 in board):
return "Illegal board"
else:
all_possible_hands = list(itertools.combinations(seven_card_hand, 5))
for hand in all_possible_hands:
evaluated_all_possible_hands.append(ranked_hands_dict[tuple(sorted(hand))])
return max(evaluated_all_possible_hands)
# Function that returns a list of possible boards given the dead cards
def create_allowed_boards(cards):
list_of_allowed_boards = []
for board in boards:
if not any(karta in cards for karta in board):
list_of_allowed_boards.append(board)
return list_of_allowed_boards
hand1 = ['2h','7d']
hand2 = ['Ad','Ah']
# HAND vs. HAND EVALUATOR
t0 = time.time()
one = 0
two = 0
tie = 0
deadcards= hand1 + hand2
list_of_possible_boards = create_allowed_boards(deadcards)
for board in list_of_possible_boards:
hand1rank = find_the_best_hand(board, hand1[0], hand1[1])
hand2rank = find_the_best_hand(board, hand2[0], hand2[1])
if hand1rank > hand2rank:
one = one + 1
if hand1rank < hand2rank:
two = two + 1
if hand1rank == hand2rank:
tie = tie + 1
onepercent = (one/len(list_of_possible_boards))*100
twopercent = (two/len(list_of_possible_boards))*100
tiepercent = (tie/len(list_of_possible_boards))*100
print(onepercent, twopercent, tiepercent)
t1 = time.time()
total = t1-t0
print(total)
最佳答案
我注意到您方法中的一个广泛主题可能需要重新评估,因为它可能会对性能产生重大影响。
听起来您正试图蛮力解决这个问题。如果我现在让你比较 2 手牌(没有电脑,只有你的大脑),你会引用你存储在内存中的每一个可能的扑克手牌的预先计算列表吗?你有没有看过这样的 list (实际上是坐下来通读每一行)?我希望不会,我猜这两个问题的答案都是“不”。
那么,您为什么选择该策略来解决程序中的相同问题呢?相反,您能否编写一个包含每种牌手类型的抽象定义的程序?这样您的程序就能够识别“皇家同花顺”或“满堂彩”?然后它只需要计算有问题的 2 手的相对值,并比较结果以确定更好的手。没有要扫描的大查找表,我敢打赌,它可以在没有比你已经拥有的更多代码的情况下完成(但你可能需要放弃你已经拥有的东西并重新开始)。
如果您仍然想追求使用预先计算的查找表的策略,这里有几个建议:
{ key : value }
.这意味着当通过指定整个键而不是其他任何内容(my_dict[key]
)来访问记录时,操作可以在固定的时间内完成,不会随着表的增长而增加(与列表相反,它需要要线性遍历的列表,直到找到匹配的记录,或者检查了所有记录但没有匹配)。创建字典时,请确保构造键的方式与以后访问它的方式完全匹配。 itertools
可能还有collections
.虽然这些是非常方便的库,但它们也隐藏了算法设计的一些非常基本和重要的方面。如果这被分配为本科计算机科学类(class)的家庭作业,那么这些图书馆很可能不会被允许。 This article比我解释得更好(这是 2001 年的乔尔,你还能要求什么?)。 from collections import Counter, namedtuple
SUITS = ['d', 'h', 's', 'c']
RANKS = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Card = namedtuple('Card', ['suit', 'rank'])
class Hand:
def __init__(self, hand):
self.hand = hand
self.catg = None
self.high_card_ranks = []
self.hand.sort(key=(lambda c: c.rank), reverse=True)
self._classify_hand()
def __eq__(self, x_hand):
return self._comp_hand(x_hand) == 'EQ'
def __lt__(self, x_hand):
return self._comp_hand(x_hand) == 'LT'
def __gt__(self, x_hand):
return self._comp_hand(x_hand) == 'GT'
def __repr__(self):
face_cards = {1: 'A', 11: 'J', 12: 'Q', 13: 'K', 14: 'A'}
repr_str = ''
for n in range(0, 5):
repr_str += str(face_cards.get(self.hand[n].rank,
self.hand[n].rank)) \
+ self.hand[n].suit + ' '
return repr_str
def _classify_hand(self):
rank_freq = list(Counter(card.rank for card in self.hand).values())
suit_freq = list(Counter(card.suit for card in self.hand).values())
rank_freq.sort()
suit_freq.sort()
if self._is_straight() and suit_freq[0] == 5:
self.catg = 'SF'
self.high_card_ranks = [c.rank for c in self.hand]
self._wheel_check()
elif rank_freq[1] == 4:
self.catg = '4K'
self.high_card_ranks = [self.hand[2].rank,
(self.hand[0].rank
if self.hand[0].rank != self.hand[2].rank
else self.hand[4].rank)]
elif rank_freq[1] == 3:
self.catg = 'FH'
self.high_card_ranks = [self.hand[2].rank,
(self.hand[3].rank
if self.hand[3].rank != self.hand[2].rank
else self.hand[1].rank)]
elif suit_freq[0] == 5:
self.catg = 'F'
self.high_card_ranks = [c.rank for c in self.hand]
elif self._is_straight():
self.catg = 'S'
self.high_card_ranks = [c.rank for c in self.hand]
self._wheel_check()
elif rank_freq[2] == 3:
self.catg = '3K'
self.high_card_ranks = [self.hand[4].rank, self.hand[0].rank]
self.high_card_ranks.append(self.hand[3].rank
if self.hand[1].rank in self.high_card_ranks
else self.hand[1].rank)
elif rank_freq[2] == 2:
self.catg = '2K2'
self.high_card_ranks = [self.hand[0].rank,
self.hand[2].rank,
self.hand[4].rank]
elif rank_freq[3] == 2:
self.catg = '2K'
self.high_card_ranks = list(set(c.rank for c in self.hand))
else:
self.catg = None
self.high_card_ranks = [c.rank for c in self.hand]
def _is_straight(self):
return ((False not in [(self.hand[n].rank == self.hand[n+1].rank + 1)
for n in (0, 1, 2, 3)])
or ([c.rank for c in self.hand] == [14, 5, 4, 3, 2]))
def _wheel_check(self):
# allows for the correct ordering of low ace ("wheel") straight
if (self.catg in ['SF', 'S']
and self.high_card_ranks == [14, 5, 4, 3, 2]):
self.high_card_ranks.pop(0)
self.high_card_ranks.append(1)
def _comp_hand(self, comp_hand):
ret_val = 'EQ'
catg_order = [None, '2K', '2K2', '3K', 'S', 'F', 'FH', '4K', 'SF']
curr_hand_catg = catg_order.index(self.catg)
comp_hand_catg = catg_order.index(comp_hand.catg)
if curr_hand_catg > comp_hand_catg:
ret_val = 'GT'
elif curr_hand_catg < comp_hand_catg:
ret_val = 'LT'
else:
for curr_high_card, comp_high_card in \
zip(self.high_card_ranks, comp_hand.high_card_ranks):
if curr_high_card > comp_high_card:
ret_val = 'GT'
break
elif curr_high_card < comp_high_card:
ret_val = 'LT'
break
return ret_val
>>> from poker_hand import *
>>> h1=Hand([Card('s', 2), Card('s', 3), Card('s', 4), Card('s', 5), Card('s', 6)])
>>> h2=Hand([Card('c', 2), Card('c', 3), Card('c', 4), Card('c', 5), Card('c', 6)])
>>> h3=Hand([Card('c', 2), Card('c', 3), Card('c', 4), Card('c', 5), Card('c', 14)])
>>> h4=Hand([Card('d', 2), Card('d', 3), Card('d', 4), Card('d', 5), Card('d', 14)])
>>> h1
6s 5s 4s 3s 2s
>>> h3
Ac 5c 4c 3c 2c
>>> h1>h3
True
>>> h3>h1
False
>>> h1==h1
True
>>> h3==h4
True
>>> h2==h1
True
from itertools import combinations, product
from random import sample, shuffle
import poker_hand
class Texas_Hold_Em(object):
def __init__(self, player_count=2):
self.player_count = player_count
self.players = []
self.comm_cards = []
self.deck = [poker_hand.Card(*c)
for c in product(poker_hand.SUITS, poker_hand.RANKS)]
def __str__(self):
face_cards = {1: 'A', 11: 'J', 12: 'Q', 13: 'K', 14: 'A'}
comm_cards = ""
for c in self.comm_cards:
comm_cards += str(face_cards.get(c.rank, c.rank)) + c.suit + " "
rv = "-" * 40 + f"\n\nCommunity Cards:\n{comm_cards}\n" + "*" * 20 + "\n"
for ct, player_hand in enumerate(self.players):
player_cards = ""
for c in player_hand:
player_cards += str(face_cards.get(c.rank, c.rank)) + c.suit + " "
rv += f"Player {str(ct)}: {player_cards}\n"
winners = self.who_wins()
rv += "*" * 20 + "\n"
for winner in winners:
rv += f"Player {str(winner[0])} wins: {str(winner[1])}\n"
rv += "\n" + "-" * 40
return rv
def deal_cards(self):
self.comm_cards.clear()
self.players.clear()
shuffle(self.deck)
dealt_cards = sample(self.deck, (2 * self.player_count) + 5)
for player in range(self.player_count):
self.players.append([dealt_cards.pop(n) for n in range(2)])
self.players[player].sort()
self.comm_cards.extend(dealt_cards)
self.comm_cards.sort()
def who_wins(self):
highest_hands = []
for player, hand in enumerate(self.players):
card_pool = self.comm_cards.copy()
card_pool.extend(hand)
card_combinations = [list(cards) for cards in combinations(card_pool, 5)]
highest_hands.append(max([poker_hand.Hand(h) for h in card_combinations]))
winning_hand = max(highest_hands)
winners = []
for player in range(highest_hands.count(winning_hand)):
idx = highest_hands.index(winning_hand)
winners.append((idx, highest_hands.pop(idx)))
return winners
>>> import texas_hold_em
>>> th=texas_hold_em.Texas_Hold_Em()
>>> for _ in range(10):
... th.deal_cards()
... print(th)
...
----------------------------------------
Community Cards:
3c 6c 2s 7s Js
********************
Player 0: Jc Jd
Player 1: 4c Ks
********************
Player 0 wins: Js Jc Jd 7s 6c (3K)
----------------------------------------
[etc...]
关于python - 如何加快我的 Python 扑克手与手牌赢率计算器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59435354/
我使用 QBFC v13 和 Delphi XE6。 目标是从我的应用程序创建 Estimate 并将其参数设置到 QuickBooks 中。 我从 QBFC13 导入类型库并将其添加到我的项目中。
我有一个数据库,其中有很多格式不正确的地址。在这个地址中,我只有一个街道地址或带有城市名称的街道。在我的应用程序中,用户选择一些类别,然后我想在 map 上显示例如 50,100,300 等地址。(不
在大多数软件项目中,缺陷源自需求、设计、编码和缺陷更正。根据我的经验,大多数缺陷都源于编码阶段。 我有兴趣了解软件开发人员使用哪些实用方法来降低缺陷注入(inject)率。 我已经看到以下方法的使用取
我正在使用实时 API 中的标签订阅构建一个应用程序,并且有一个与容量规划相关的问题。我们可能有大量用户同时发布到订阅的主题标签,因此问题是 API 实际发布到我们的订阅处理端点的频率是多少?例如,如
尝试使用 NULLIF 或 IFNULL 函数,但仍收到被零除的消息。 SELECT client_id ,COUNT(distinct CASE WHEN status = 'failed' THE
我目前正在开发一个使用 Django-rest-framework 制作的 API。我必须根据每个用户组设置限制率。 我们目前使用默认配置的 memcached 作为缓存后端,即按站点缓存。 在使用
我认为有时在神经网络(特别是一般对抗网络)训练期间改变丢失率可能是一个好主意,从高丢失率开始,然后线性地将丢失率降低到零。您认为这有意义吗?如果是的话,是否有可能在 tensorflow 中实现这一点
我有一个 Windows Server 2008,Plesk 运行着两个网站。有时服务器运行缓慢,并且有一个 named.exe 进程使 CPU 峰值达到 100%。它持续很短的时间,过一会儿它又来了
我正在使用 scikit-learn 随机森林分类器,我想通过将成功投票所需的树数量从大于 50% 增加到 75% 来降低 FP 率,在阅读文档后我不这样做确定如何做到这一点。有没有人有什么建议。 (
当我连续按下按键事件(字母 k)时,为什么以下按键事件不会减慢 3000 密耳?如果我按住手指,计数会迅速增加,因为 mcount 上没有 setTimeout。这是为什么?每次计数之间应该有延迟,但
我是一名优秀的程序员,十分优秀!