德州扑克逻辑

     最近在写德州扑克的游戏,在此记录下。从操作(call,check,flod,raise,allin)到网络通讯到判断是否一轮结束,以及最后的结算算法。

    本想在网上找找现成的算法代码直接整合进来,可是没有找到全的,只有一些零散的逻辑代码,可能是我没找对地方吧,总而言之,最后自己重写了一遍。在此记录下,也是为自己再过一遍逻辑。

    首先,列举下德州扑克中的术语,在看别人的代码或自己写代码的时候,知道的话会很方便。

  1. Leader,SmallBlind(小盲),BigBlind(大盲)。大小盲位置的玩家在开局的时候,就需要下注(自动下注),下注金额是提前定好的,一般大盲注是小盲注的2倍。
  2. 玩家的操作:call(跟注),check(让牌),fold(弃牌),raise(加注),allin(全下),其中call和check意思相近,这两种操作,从逻辑上可以划分为一类,check就是跟注为0的call(我在我的逻辑中就是这样实现的),但是在UI显示的时候要做区分,这两者的UI不会同时出现,因为需要跟注的时候,不能让牌,可以让牌的时候,不需要跟注。
  3. 翻牌的前三张,称为flop,翻第四张,称为turn,翻第五张牌,称为river。
  4. 牌型:RollyFlush(皇家同花顺,同花色的AKQJ10),Straight Flush同花顺),FourofaKind(四条),Full House(葫芦,三条加一对),Flush(同花),Straight(顺子),ThreeOfAKind(三条),TwoPair(两对),Pair(一对),HighCard(高牌)

   游戏开始,确定Leader位置和大小盲位置,大小盲自动下注。此处要做一个判断,因为大小盲必须存在,而且不能是同一个人,所以游戏开始的其中一个条件是玩家数大于等于2。如果玩家数等于2,房主是leader,房主的下一家是小盲,小盲的下一家是大盲,即房主既是leader,又是大盲。大小盲下注后,由小盲先说话(每一轮开始,都从小盲开始说话,若小盲不在,则从小盲的下家开始说话,以此类推)。小盲说话后,大盲说话。

   我的设置是,在显示玩家操作UI(call,check,flod,raise,allin)前,判断玩家可以有哪些操作。这样做的好处是,当我执行call,raise,check,allin时,不用再判断此操作是否有效,只执行正常的逻辑就可以了。判断call的逻辑是,玩家桌面上的筹码和手里剩下的筹码加起来大于LastBet(定义下,什么是LastBet,之前的玩家中下注最多的一个人桌面上的所有筹码,此玩家桌面上的所有筹码就为LastBet,举个例子,大小盲自动下完注后,LastBet为大盲注,小盲call,LastBet仍为大盲注,小盲加注,LastBet就为小盲桌面上的所有筹码,因为此时小盲的下注比其他人都多。以此类推),同时不等于LastBet(因为若等于LastBet,玩家就可以check了)。check的判断逻辑:玩家桌面上的筹码等于LastBet。raise的判断逻辑:玩家桌面上的筹码和手里剩下的筹码加起来大于(LastBet+最小加注值)。fold和allin按钮一直显示,玩家随时可以弃牌和全下。

   allin是一个特殊的行为,处理起来异常复杂,这也是让我非常头疼的地方。复杂的原因在于,1:玩家allin可能有两种情况,一种是allin后,玩家的所有下注仍可以小于LastBet,这种情况在判断一轮是否结束时,需要加判断;一种是allin后,玩家的所有下注大于LastBet,LastBet更新。2:allin后,会出现边池,需要划分出边池的大小,在最后结算时,需要多加很多很多判断。首先说下,如何判断一轮是否结束,是否可以开牌或一局是否结束。

   判断一轮是否结束。每一个玩家执行完操作后,都需要判断下是否结束。我在玩家的类(class)中定义了一个bool值,isTalked,用来标志玩家在此轮中是否已说过话,因为每一轮,每一个还在局中的玩家都有权利说话。玩家执行操作时,isTalked设置为true。但是,但是有一种情况,在一轮中,isTalked需要再重置,就是当有玩家allin,并且玩家allin后,LastBet更新了。这个时候需要重置其他玩家的isTalked。这是为什么呢?我先说下我的判断一轮是否结束的条件(第一轮要做特殊处理,大盲必须主动说话一次):所有玩家都说过话,所有玩家的下注值一样或不同于其他玩家下注值的玩家allin了。因为玩家allin后,下注值可以小于其他玩家,而且之后,此玩家不再有说话的机会。如果玩家allin后下注值都小于LastBet,那上面的判断就可以了。但是玩家allin后,还可能会更新LastBet,即下注值大于之前的玩家的下注值,这个时候,“所有玩家的下注值一样或不同于其他玩家下注值的玩家allin了”这个条件就有问题了,因为按照游戏规则,如果中间有人allin值大于其他人,后面的人,以及前面的人,都需要重新做操作。其实这个地方还有其他方法,我只是偷了个懒,用已有的属性来标识,当一个玩家allin,并且allin后的下注值大于LastBet,其他未allin的玩家都需要重新说话(写博客真的有用,我这个地方漏了一点,我现在的逻辑写的是“其他玩家都需要重新说话”,而不是“未allin的玩家”,惭愧惭愧。。。已allin的玩家已经没有机会说话了。。)。这样的话,“所有玩家都说过话,所有玩家的下注值一样或不同于其他玩家下注值的玩家allin了”的判断条件就可以了。

   说下raise的执行逻辑,因为我在刚开始写的时候,没有多想,直接写成了加多少注就增加多少注,其实不是,raise的意思是,在call的基础上的raise。假如:LastBet等于120,你已下注值是50,这个时候你选择加注80,这个时候,你拿出的筹码应该是120-50+80=150,70是跟注,80是加注。很小的点,但也算是个坑。

  call的逻辑,就是补足LastBet的值,这个不多说了。 

  checkt的逻辑,就是call的逻辑,只是控制UI显示的时候,做下判断。

  allin的逻辑,首先需要类中定义个变量标识此玩家allin了,isAllined(在判断一轮是否结束时用得到),然后记下这个玩家对象和allin值(allin值,下注值:玩家所有下注的筹码),放到一个公共数组allinPlayers中,然后在一轮结束时,分池。首先对allinPlayers数组排序,然后allin值大的玩家需要拿出小于自身allin值的玩家的allin值。比如:a玩家allin值2000,b玩家allin1600,c玩家2700,当一轮结束后,a玩家和c玩家需要各自拿出1600到b玩家的池中,此时a玩家的allin值就是2000-1600=400了,c玩家还需要拿出400到a玩家的池中,c玩家的allin值就是2700-1600-400=700.然后获得其他所有玩家的下注值,按照allin值从小到大的顺序,各自拿出相应allin玩家的allin值,即每个玩家都给a玩家的池中加入1600,给b玩家的池加入400,给c玩家的池加入700.这样就分成了三个池,a玩家一个池,b玩家一个池,c玩家一个池。剩余玩家的剩余下注值进行下一轮。

  fold的逻辑,需要判断下还剩余几个玩家,如果只剩余一个玩家,则桌面上的所有筹码都归剩下的一个玩家,并且游戏结束。

  这让我想起来我忽略的一个地方,如果有allin玩家在一局未结束时,退出游戏了。对最后的结算有影响啊。 

   结算:先比较未allin的玩家的牌:得到所有未allin的玩家noAllinPlayers,得到未算入所有allin池中的筹码值noAllinMoney(计算牌型,我就不写了,没有什么逻辑难点,只是判断七张牌可以组成的牌型,一个点是A的情况,A要当成14来算,顺子 1,2,3,4,5除外,一个点计算牌型的时候,需要尽可能将玩家的各个牌的大小顺序得到,FirstMaxValue,SecondMaxValuse,ThirdMaxValus,FourthMaxValue,FifthMaxValue)。比较所有未allin玩家的牌的大小,得到牌值最大的玩家数组noAllinPlayersWiners(可能牌一样大),noAllinPlayersWiners平分noAllinMoney。然后noAllinMoney依次与allin玩家比较,从allin值大的开始比较(以上面的a,b,c玩家举例,先和c玩家比较,决定c玩家的allin池的归属,然后比较a玩家,b玩家)。这个地方就涉及到我上面说到的我忽略的地方了,“如果有allin玩家在一局未结束时,退出游戏了”,那退出游戏的玩家的身上的allin池中的钱归谁呢?我需要再想想。。。。

posted on   施琅水月  阅读(1877)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示