Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一道算法题:德州扑克多家ALLIN如何分筹码?算法+代码

一道算法题:德州扑克多家ALLIN如何分筹码?算法+代码

原创
作者头像
HullQin
修改于 2023-08-18 09:03:53
修改于 2023-08-18 09:03:53
6K00
代码可运行
举报
文章被收录于专栏:教你做小游戏教你做小游戏
运行总次数:0
代码可运行

难点

虽然95%以上的场景,都是一家胜出,但是你要做系统,就要覆盖100%的场景。

给你举个特殊场景的例子:

  • 玩家1: ALLIN 100 牌最大
  • 玩家2: ALLIN 200 牌也最大
  • 玩家3: ALLIN 200 牌第二大
  • 玩家4: ALLIN 400 牌也第二大
  • 玩家5: ALLIN 1000 牌第三大
  • 玩家6: ALLIN 2000 牌第四大
  • 玩家7: ALLIN 400 牌最小

整个底池:4300,这时候怎么分筹码?

你先思考一下。即使你不知道,也可以想想,如果让你来设计分法,怎么分最公平?

我可以明确告诉你:不是玩家1和2平分4300,也不是玩家1和玩家2按1:2比例分这4300。

分法

先按照所有人拥有的筹码排序:玩家1、2、3、7、4、5、6。

然后,以每人下注100作为主池,做第一次分配。

第一次分配完毕后,每人还有剩余未分配的筹码,再选最小的下注,做第二次分配,这叫边池。

以此类推,直到分配结束。如下表:

至此,分配结束。你看懂分配算法了嘛?

数据结构

我们必须要记清楚,每个玩家本局总共投入了多少筹码,才方便后续计算。

以下变量类型都是python。

第一,定义room['players']是本房间(群聊)的玩家筹码总量信息,是个dict,key是用户ID,value是个dict,形如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  'chip': 1000,  # 手上有1000筹码(对局中下注时,这里的值会实时减少,对局结束后再把赢的部分加回来)
}

第二,定义playing_seats是本局的玩家信息,是个list,每一项是个dict,形如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  'i': 1,  # 座位号,从0开始
  'id': 'uuid',  # 用户ID,跟room['players']的key对应
  'all_chip': 100,  # 本局投入的所有筹码
  'action': SeatAction.Fold,  # 最终的行动
}

其中action包括:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import enum

class SeatAction(enum.IntEnum):
    WAIT = 0
    CHECK = 1
    CALL = 2
    RAISE = 3
    ALLIN = 4
    FOLD = 5
    WIN = 6  # 胜利,不摊牌(适用其他人都Fold的情况)
    WIN_SHOW = 7  # 胜利,需要摊牌
    LOSE_SHOW = 8  # 失败,需要摊牌

开发

排序逻辑

注:cards就是所有牌,是一个长度52的list,每一项的值都是0-51,开局前会做一次shuffle(随机打乱顺序)。底牌、玩家的牌的信息,就藏在这个list中。

先计算5张底牌(PS:我是不是很严谨,按照了专业比赛的发牌顺序hhh😂):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
playerCount = len(playing_seats)
five_cards = [cards[playerCount * 2 + 1], cards[playerCount * 2 + 2], cards[playerCount * 2 + 3], cards[playerCount * 2 + 5], cards[playerCount * 2 + 7]]

计算一下每个未Fold牌玩家的牌的得分,这里get_max_score() 来自 这是一道算法题:如何比较徳州扑克牌大小?(附带python实现) 。算出得分后,按付出的筹码从小到大排序,放到final_seats里,为什么叫final呢?表示他们会最终参与到分筹码流程里(都是亮牌的人)。

此外,Fold牌的玩家,得分为(-1, -1),他们永远不会有收益(因为总有未Fold牌的人会收获他们所有筹码),所以他们不在final_seats里。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
final_seats = []
for i, s in enumerate(playing_seats):
    if s['action'] < SeatAction.FOLD:
        s['score'] = get_max_score(five_cards + [cards[i], cards[i + playerCount]])
        final_seats.append(s)
    else:
        s['score'] = (-1, -1)
final_seats = sorted(final_seats, key=lambda x: x['all_chip'])

核心逻辑

整体是个大循环,遍历final_seats,每一次遍历,表示第N次分配。

每次分配中,其他玩家每个人都要付出至多final_seat['all_chip']

每次分配,计算bonus_together,表示这轮分配的总筹码,加上赢家投入的筹码、所有输家要付出的筹码。之后本轮赢家会平分bonus_together

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
done_seats = set()
for final_seat in final_seats:
    if final_seat['i'] in done_seats:
        continue
    # 用current_chip存储本轮的最高分配额度,因为final_seat['all_chip']会变,不能一直引用final_seat['all_chip']
    current_chip = final_seat['all_chip']
    # 本轮分配的bonus_together
    bonus_together = 0
    # 以下逻辑,计算本轮分配最大牌力的玩家(们)
    max_score = (-1, -1)
    max_score_seats = []
    for other_seat in playing_seats:
        if other_seat['i'] in done_seats: 
           # 表明该玩家筹码分配完毕,就跳过该玩家
           continue
        if other_seat['score'] == max_score:
            max_score_seats.append(other_seat)
        elif other_seat['score'] > max_score:
            max_score = other_seat['score']
            max_score_seats = [other_seat]
        if other_seat['all_chip'] > current_chip:
            # 这个玩家投入的筹码超过“至多付出筹码”,只会付出“至多付出筹码”,后续还会参与下轮分配
            bonus_together += current_chip
            other_seat['all_chip'] -= current_chip
        else:
            # 这个玩家投入的筹码不够“至多付出筹码”,就全要给赢家,自己分配完毕
            done_seats.add(other_seat['i'])
            bonus_together += other_seat['all_chip']
            other_seat['all_chip'] = 0
    # 以上逻辑,计算本轮分配最大牌力的玩家(们)
    if bonus_together > 0:
        # deliver_bonus用于记录本轮分配了多少筹码,避免小数点,避免算法漏洞导致筹码总量异常
        deliver_bonus = 0
		max_score_seat = playing_seats[-1]
        for max_score_seat in max_score_seats:
            bonus = bonus_together // len(max_score_seats)  # 除数不会是0,若为0,不会进入这里逻辑
            deliver_bonus += bonus
            room['players'][max_score_seat['id']]['chip'] += bonus
        # 为了避免小数,以上计算都是向下取整,下面做个补偿。座位靠后玩家有略微优势,瓜分筹码会多分一点点。
        # 为什么是座位靠后的玩家有优势?因为庄家是从座位靠前的玩家开始轮流的,座位靠后的玩家当庄家的次数相对少一点点。
        room['players'][max_score_seat['id']]['chip'] += bonus_together - deliver_bonus

这里有个逻辑:deliver_bonus记录本轮分配了多少筹码,作用是:1、避免小数点,2、避免算法漏洞导致筹码总量异常。

通过防御式编程,降低了错账风险。事实上最初版本确实有过bug,无法正确处理平分筹码的情况。幸亏有deliver_bonus,导致筹码总量没有变多变少,系统上记录的筹码量依然有参考价值,只要通过人工简单记着我欠你xxx,结合系统上的数据,就能很快的得到正确的数据。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Deepin V23 / 统信UOS 下安装与配置 tftp
几个月前,我将开发系统从 ubuntu 切换到 Deepin,当时写过一篇文章《使用国产操作系统作为开发系统》。几个月下来,没有感觉有什么不适应,Ubuntu 能做的事情,在 Deepin 上都能做。而且有 UOS 应用商店的加持,很多 Windows/Linux 应用程序,可以直接从应用商店安装,不需要自己去配置安装,所以总体感觉比 Ubuntu 用得更顺手一些。
云水木石
2025/01/23
1510
Deepin V23 / 统信UOS 下安装与配置 tftp
基于 WireGuard 和 OpenVPN 的混合云基础架构建设
可以找一台能联网的 centos7 测试一下这个端口,如果没有 nc 工具可以yum install nc安装下。:
米开朗基杨
2021/04/23
8.2K1
基于 WireGuard 和 OpenVPN 的混合云基础架构建设
近期研究VPN的一些记录(OpenVPN,pptp,l2tp)
近期由于一些需要(特别是上Google),研究了下在VPS上搭建VPN服务器的方法。其中遇到一些坑,顺带记下来以备下次使用。
owent
2023/03/06
6.6K0
OpenVPN原理及部署使用
简介 VPN技术通过密钥交换、封装、认证、加密手段在公共网络上建立起私密的隧道,保障传输数据的完整性、私密性和有效性。OpenVPN是近年来新出现的开放源码项目,实现了SSL VPN的一种解决方案。 传统SSL VPN通过端口代理的方法实现,代理服务器根据应用协议的类型(如http,telnet等)做相应的端口代理,客户端与代理服务器之间建立SSL安全连接,客户端与应用服务器之间的所有数据传输通过代理服务器转发。这种实现方式烦琐,应用范围也比较窄:仅适用于用TCP固定端口进行通信的应用系统,且对每个需要
iginkgo18
2020/09/27
49.7K1
OpenVPN原理及部署使用
下一代VPN工具:体验TailScale的简便和高效
tailscale管理端:https://login.tailscale.com/admin/machines
小尘要自信
2023/11/16
9.4K0
下一代VPN工具:体验TailScale的简便和高效
openvpn安装及证书制作
1) 安装epel 仓库源 wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm rpm -Uvh epel-release-6-8.noarch.rpm
一朵灼灼华
2022/08/05
8.4K0
openvpn安装及证书制作
deepin V23 下运行安卓应用程序
在前一篇文章《Linux 系统运行 Android 应用的几种方案》中介绍了几种在 Linux 系统上运行Android 应用的方案。其实统信 UOS/deepin 也有自己的 UEngine 方案来运行 Android 应用。UEngine 方案基于 anbox 二次开发,可惜的是不再维护,在 deepin v23 中已经移除。UOS 应用商店中的 Android 应用也越来越少。
云水木石
2025/03/24
3400
deepin V23 下运行安卓应用程序
CentOS 7 部署 OpenVPN
环境: 外网IP:139.198.15.121 内网IP:10.180.27.8
陳斯托洛夫斯記
2022/10/27
8.2K1
CentOS 7 部署 OpenVPN
Deepin 下 使用 Rider 开发 .NET Core
Deepin 用了也有一两年,也只是玩玩,没用在开发上面。后来 Win10 不太清真了,就想着能不能到 Deepin下撸码。要搞开发,首先少不了 IDE,VS2019 用不来,Vs Code 太复杂、麻烦,后来发现了 Rider 这个神器,可是 Rider 是英文界面,笔者的英文是渣渣的。结果在 Windows 下 使用 Rider 开发一段时间后, 已经熟悉了 Rider ,于是计划后面迁移到 Deepin 下开发 .NET Core 。笔者装了双系统 Windows10 + Deepin 15。
痴者工良
2021/04/26
1K0
在龙芯迷你电脑上搭建开发环境
之前我写过一篇文章《龙芯迷你主机,用来办公怎么样?》,到现在已经使用了一段时间。整体体验下来,系统是可用的,但离完美仍有差距,主要原因是龙芯生态中的应用还非常匮乏。原本在 UOS 系统下,应用就比 Windows 少很多,而龙芯版 UOS 系统的应用更加稀缺。
云水木石
2025/01/23
2520
在龙芯迷你电脑上搭建开发环境
[经验分享] 腾讯云ubuntu搭建openvpn
./build-dh 命令完成后,我们会/usr/share/doc/openvpn/examples/easy-rsa/2.0/keys 得到 ca.crt、ca.key、dh1024.pem 等文件。其中,ca.key 的安全非常重要,OpenVPN 并不需要这个文件,所以可以存放在其他比较安全的地方,否则,OpenVPN 的通信将不再安全。 cp /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/server.crt /etc/openvpn/ cp /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/server.key /etc/openvpn/ cp /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/dh1024.pem /etc/openvpn/ cp /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/ca.crt /etc/openvpn/ 生成服务端证书 ./build-key-server server
知识与交流
2023/03/25
12.8K0
[经验分享] 腾讯云ubuntu搭建openvpn
Deepin 极简主义 -- dwm
dwm 是X的动态窗口管理器。它管理平铺、单镜头和浮动布局的窗口。所有的布局都可以动态应用,优化了使用中的应用程序和执行的任务的环境。官网:https://dwm.suckless.org/
caoayu
2021/02/24
2.2K0
国产系统之如意玲珑
在使用 Deepin/UOS 系统时,我注意到应用商店新增了一个“玲珑应用”的类别。经过一番了解,发现这是一种最新研发的国产软件包格式——如意玲珑。那么,什么是如意玲珑?为什么要开发这样一种全新的软件包格式?这篇文章就带大家深入探索如意玲珑的世界。
云水木石
2025/01/23
2790
国产系统之如意玲珑
CDH安装与部署
访问CM, 登录地址 http://localhost:7180 默认账号密码为: admin/admin
mikelLam
2022/10/31
8830
CDH安装与部署
国内程序员的Linux开发平台-Deepin
导读 研发工作了这么长时间,一直在Windows平台做研发工作,期间也纠结过Linux和Mac平台,经过一番自我分析,决定使用Linux环境作为主要开发环境,Linux环境版本众多,先尝试了Unbuntu(乌班图),一个成熟稳定的Linux桌面平台,既可以通过终端完成操作,又可以在可视化的桌面操作。但是体验下来,对国内软件非常不友好,而且需要花费大量的时间去安装各种应用来美化和完善。最终选择Deepin这款国产Linux平台,界面美观,国内常用应用安装方便且版本新,有活跃社区可以解答Deepin的使用问题,
翟凤玺
2021/12/07
2.9K0
国内程序员的Linux开发平台-Deepin
ubuntu部署VPN中openvpn(上)
如果在一个非信任网络下比如旅社或者咖啡店的WiFi网络下,想要通过你的智能手机或者笔记本电脑安全地访问互联网,那么VPN可以满足你的要求。VPN(VirtualPrivate Network)允许你私有地(privately)安全地(securely)穿过非信任的网络,就好像为你建立了一条专属网络。你的数据流量到达VPN服务器之后,VPN服务器继续将你的网络流量送达目的地。
陈不成i
2021/06/30
15.7K0
Deepin-环境配置
系统问题 --- 一、开机、关机、锁屏卡住 问题:显卡兼容问题。 解决方案: 进入应用商店下载 显卡驱动管理器 安装 使用开源驱动 二、创建桌面图标 创建一个文件,后缀名为 *.desktop 文件内容: [Desktop Entry] Type=Application Name=Firefox 开发者版 Icon=/home/wang/桌面/Firefox/firefox/default64.png Exec=/home/wang/桌面/Firefox/firefox/firefox Terminal=f
无名小辈
2020/11/15
8400
使用Lighthouse搭建OpenVPN轻松访问内网服务
OpenVPN是一种功能强大的开源虚拟私有网络(VPN)解决方案,可以在多种应用场景下使用。以下是几个常见的OpenVPN应用场景:
小宇-xiaoyu
2023/11/28
3.2K0
Ubuntu-20.04-LTS(桌面与服务器)版基础配置
Ubuntu 20.04 是 Ubuntu 的第 8 个 LTS 版本代号为"Focal Fossa"; 下载地址: http://releases.ubuntu.com/20.04/ 下载镜像时可以选择以下两种镜像:
全栈工程师修炼指南
2022/09/29
7.1K0
Ubuntu-20.04-LTS(桌面与服务器)版基础配置
deepin V25 预览版发布!5 大亮点引领未来体验
在《不要重复发明轮子!谷歌:我偏要》一文中,我们聊到了,并非所有的技术创新都需从零开始。即使是谷歌这样的巨头,也会从开源项目起步,当掌握相关技术后,再决定是否完全自研。文章结尾还提到,国产操作系统 deepin 采用类似路径,早期基于 Debian 构建国人友好的操作系统,在时机成熟时,deepin 团队果断决定绕过上游社区,直接基于 Linux Kernel、其他开源项目及自研组件,建立一个独立的中国桌面操作系统根社区,从而进一步掌握操作系统发展方向的主导权。。
云水木石
2025/01/23
2910
deepin V25 预览版发布!5 大亮点引领未来体验
相关推荐
Deepin V23 / 统信UOS 下安装与配置 tftp
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验