首先声明:我是一名医学专业人士,业余爱好是玩Python和扑克。我在这两个方面都没有受过正规的培训,我也不知道计算机科学课的课程是什么。 我使用的电脑是台式机i7-47903.6ghz,16gb的RAM和Jupyter笔记本。在
我的目标是编写相当于扑克战略网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
所以它区分了9 8 7 3和9 8 7 5平齐或高手。我用理论上的皇家冲锋次数,四舍五入,满屋数等检查了259860张卡片组合和频率检查(https://www.quora.com/How-many-possible-hands-are-there-in-a-five-card-poker-game)
现在我试着从这260万张中找出每一张可能的5张牌组合,结果花了令人失望的51秒。在
我有点期待我的5张卡片评估器不能成为算法竞赛的冠军,当然还有更好的方法(如果有关联,我可以把它贴在这里),但我想没关系。一旦所有的5卡组合被评估,我将把它们保存在字典中,下次我将加载字典,当我有任何5卡组合时,我将简单地查找结果。在
又一次失望。10万(1000万)的董事会搜索大约需要23-24天秒。这个是一个我不明白的部分!!!我基本上有一个260万的数据库。行x 2列,搜索速度太慢了。那么十亿的记录数据库是如何完成的呢?我的整个字典保存到一个文件中需要88MB——这是一个巨大的数据库吗?在
最后,我制作了一个完整的手对手求值器,在伪代码中可以做到:
举双手,例如AhAs vs.6d6h
列出所有可以处理这2张“死”牌的牌,即1 712 304张牌
列出hand1与board 1的所有21种组合,
用这21个组合搜索排名的_hands字典,并返回可能的最佳结果(21个组合,因为在texas holdem,您可以使用手上的一张、两张或不使用手牌上的5张社区卡中的任何一张)
对hand2和board1执行相同的操作
比较hand1的最佳结果与hand2的最佳结果
如果结果有利于第1手、第2手或是平局,则计数
转到下一个板
这个算法大约要查找7100万个字典-每个170万个板x 42(每只手的21个组合两次)。在
现在,这是一场灾难。每手大约80秒对手对决。 以这样的速度,我什么也不能开始。 所以,如果我能把这件事做得更好,我将不胜感激?在
是我和我缺乏适当的计算机科学和算法知识吗?在
是Python吗? 是Chrome内部的Jupyter笔记本吗?在
还有其他建议吗?在
要求的代码:
^{pr2}$也许一次打印(总计)多份,但最初是在Jupyter笔记本上
我已经仔细阅读了你的代码。我认为预先计算每只手牌的等级的方法是可行的,尽管它看起来很野蛮。你关于在大多数情况下必须评估每一个踢球员的观点似乎是这种方法的合理理由。在
编辑-一些在线研究表明这不是一个小问题,目前最好的解决方案是“2+2”方法,它实际上是基于查找,但有一些重大的优化。 https://web.archive.org/web/20111103160502/http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup#2p2
一些一般要点:
然而,我一直在努力从代码中挤出更多的速度。事实上,我觉得现在慢了一点!通过尽可能使用集合并删除一些不必要的中间变量,我稍微整理了一下,但从根本上看,运行时的大部分时间都被字典查找消耗掉了。每一个都很快,但有太多的一切加起来。这里值得的是我对你的代码的版本。我没有使用Jupyter,所以我稍微重构了一下,将字典保存到磁盘上。我没有想到比你的算法更好的算法,所以我会继续思考!在
您可以使用dbm模块(请参见https://docs.python.org/3/library/dbm.html)或python2.x中的bsddb将整个查找表存储在数据库文件中,如果它太大而无法放入dict中的内存,那么填充该表可能需要一些时间,但只需执行一次。在
我注意到你的方法中有一个广泛的主题,可能是一个值得重新评估的话题,因为它可能会在性能上产生实质性的差异。
听起来你在试图强行解决这个问题。如果我要求你现在比较两只手(没有电脑,只有你的大脑),你会参考你存储在内存中的每一个可能的扑克手的预先计算的列表吗?你有没有看过这样的清单(实际上是坐着读过每一行)??我希望不会,我猜这两个问题的答案都是“不”。
那么,为什么你选择这个策略来解决你的程序中的相同问题呢?相反,您能编写一个程序,其中包括扑克手的每个类型的抽象定义?这样你的程序就能识别“皇室冲水”还是“满屋”?然后只需计算出所涉双手的相对值,并将结果进行比较,以确定更好的手。没有大的查找表可以扫描,我敢打赌,它可以在没有比您已经拥有的代码更多的情况下完成(但是您可能需要废弃您已经拥有的并重新开始)。
如果您仍然想采用使用预先计算的查找表的策略,请提供以下几点建议:
并且,无论您选择了何种方法:
编辑
^{pr2}$这里有一个类实现了扑克牌,并通过使用“>;”、“<;”和“=”直接比较两个实例,在任意一组手上传递订单。没有查找表。
相关问题 更多 >
编程相关推荐