9

我正在尝试运行扑克模拟并获得有关扑克桌的以下数据

  • 每个玩家为底池贡献了多少
  • 每个玩家的“手牌得分”(翻牌后)(即,如果player[0].score == player[1].score,他们并列)

我一直在计算每个玩家应该赢多少,而无需创建边池并将玩家分配给每个玩家。

例如,

player[0].contributed = 100
player[1].contributed = 80
player[2].contributed = 20

player[0].score = 10
player[1].score = 2
player[2].score = 10

total_pot = 200;

在这个例子中,我是否首先需要将player[0]20 退回并从锅中取出?

那么,既然player[0]player[2]并列第一,并且player[1]已经输了,那么底池应该被划分为:

player[0].received = 170
player[1].received = 0
player[2].received = 30

随后,如果player[1]赢了,底池应该被分成:

player[0].received = 20
player[1].received = 180
player[2].received = 0
4

3 回答 3

10

首先按分数降序排序,因此您最终会得到两组:{ 0, 2 }, { 1 }。

然后,按照他们贡献的升序对每个组进行排序:{ 2 (20), 0 (100) }, { 1 (80) }。

现在,按顺序划分底池:

  1. 首先,您将从每个玩家的贡献中抽取(最多)20 分来创建第一个底池。并将其平均分为 2 和 0。第一个底池将是 (20 + 20 + 20 = 60。所以 0 和 2 都将得到 30)。之后,第一个玩家的奖金就完成了,剩下的就是:{ 0 (80) }, { 1 (60) }。

  2. 现在,您将从每个玩家的贡献中抽取(最多)80 来创造下一个底池(80 + 60 = 140)。并将其设为 0(不需要除法,因为顶部组中不再超过一个,因此 0 将接收整个 140)。您将得到:{ 1 (0) }。

  3. 没有更多的贡献了,所以你完成了。

因此,在您的示例中,0 将收到 170,2 将收到 30。

于 2011-03-28T17:34:08.007 回答
2

下面的代码有非常多的断言,但是要小心,因为我没有仔细测试过。目前尚不清楚如何处理奇数筹码。我把它们交给收藏品中稍后出现的玩家。

import java.util.*;

public class Player {
    int contributed, score, received;

    static void winnings(Collection<Player> players) {
        for (Player player : players) {
            assert player.contributed >= 0;
            player.received = 0;
        }
        int potCutoff = 0;
        while (true) {
            int playerCount = 0;
            int nextPotCutoff = Integer.MAX_VALUE;
            int scoreMax = Integer.MIN_VALUE;
            int winnerCount = 0;
            for (Player player : players) {
                if (player.contributed <= potCutoff) {
                    continue;
                }
                playerCount++;
                assert playerCount > 0;
                nextPotCutoff = Math.min(nextPotCutoff, player.contributed);
                if (player.score > scoreMax) {
                    scoreMax = player.score;
                    winnerCount = 1;
                } else if (player.score == scoreMax) {
                    winnerCount++;
                    assert winnerCount > 0;
                } else {
                    assert player.score < scoreMax;
                }
            }
            if (playerCount == 0) {
                break;
            }
            assert playerCount > 0;
            assert nextPotCutoff > potCutoff;
            assert potCutoff >= 0;
            assert Integer.MAX_VALUE / (nextPotCutoff - potCutoff) >= playerCount;
            int potTotal = playerCount * (nextPotCutoff - potCutoff);
            assert potTotal > 0;
            assert winnerCount > 0;
            assert winnerCount <= playerCount;
            for (Player player : players) {
                if (player.contributed <= potCutoff) {
                    continue;
                }
                assert player.contributed >= nextPotCutoff;
                if (player.score == scoreMax) {
                    assert winnerCount > 0;
                    int winnerShare = potTotal / winnerCount;
                    winnerCount--;
                    assert winnerShare > 0;
                    assert potTotal >= winnerShare;
                    potTotal -= winnerShare;
                    player.received += winnerShare;
                    assert player.received > 0;
                } else {
                    assert player.score < scoreMax;
                }
            }
            assert winnerCount == 0;
            assert potTotal == 0;
            potCutoff = nextPotCutoff;
        }
    }

    public static void main(String[] args) {
        Player p0 = new Player(), p1 = new Player(), p2 = new Player();
        p0.contributed = 100;
        p1.contributed = 80;
        p2.contributed = 20;
        p0.score = 10;
        p1.score = 2;
        p2.score = 10;
        Collection<Player> players = new ArrayList<Player>();
        players.add(p0);
        players.add(p1);
        players.add(p2);
        winnings(players);
        for (Player player : players) {
            System.out.println(player.received);
        }
    }
}
于 2014-04-15T18:11:23.507 回答
0

我添加了一条额外的信息,一个折叠的标志。之后,该代码完全可用于解决底池分配问题。我想我基本上使用了 Sami 的算法建议。我有一个用 C# 编写的解决方案:

using System;
using System.Collections.Generic;

public class Player
{
    public ulong potCommitment;
    public uint handStrength;
    public ulong chipsRemaining;
    public bool folded = false;
    public Player(ulong pc, uint hs, ulong chipsBehind, bool isFolded): this(pc, hs, chipsBehind)
    {
        folded = isFolded;
    }

    public Player(ulong pc, uint hs, ulong chipsBehind)
    {
        potCommitment = pc;
        handStrength = hs;
        chipsRemaining = chipsBehind;
    }
}
/*
Player A has first action with $50 chips and decides to go all in. Player B raises to $150. 
Player C has only $70s worth of chips and decides to go all in. Player D only has $20 and goes all in. 
*/
public class Program
{
    public static List<Player> winners = new List<Player>();
    public static List<Player> players = new List<Player>();
    public static void Main()
    {
        players.Add(new Player(50, 100, 0));
        players.Add(new Player(150, 80, 0));
        players.Add(new Player(70, 100, 0));
        players.Add(new Player(20, 150, 0));
        
        // Loop through players until no unclaimed chips in pot.
        while (PotChipsRemaining(players) > 0)
            PayOutWinners(CalculateAndSortWinners(players), players);

        // Refund folded players if remaining chips in pot
        foreach (var player in players)
        {
            player.chipsRemaining += player.potCommitment;
            player.potCommitment = 0;
        }

        Console.WriteLine($"***********************\nFinal results:");
        PotChipsRemaining(players);
    }

    // TODO: Split Pots
    public static List<Player> CalculateAndSortWinners(List<Player> playersInHand)
    {
        uint highHand = 0;
        // Get highHand, skipping folded players and those without any commitment left
        foreach (var player in players) if (player.potCommitment > 0 && !player.folded)
        {
            if (player.handStrength > highHand)
            {
                winners.Clear();
                highHand = player.handStrength;
                winners.Add(player);
            }
            else if (player.handStrength == highHand)
            {
                winners.Add(player);
            }
        }

        winners.Sort((x, y) => x.potCommitment.CompareTo(y.potCommitment));
        return winners;
    }

    public static void PayOutWinners(List<Player> winners, List<Player> playersInHand)
    {
        ulong collectedSidePot;
        ulong currentCommitment, collectionAmount;
        List<Player> paidWinners = new List<Player>();
        // for each playerPot in winners
        foreach (var playerPot in winners)
        {
            collectedSidePot = 0;
            currentCommitment = playerPot.potCommitment;
            // Collect it from all players who have money in pot
            foreach (var player in playersInHand) if (player.potCommitment > 0)
                {
                    collectionAmount = Math.Min(currentCommitment, player.potCommitment);
                    player.potCommitment -= collectionAmount;
                    collectedSidePot += collectionAmount;
                }

            int winnersToPay = 0;
            
            foreach (var player in winners) if (paidWinners.IndexOf(player) == -1) winnersToPay++;

            Console.WriteLine($"collectedSidePot: {collectedSidePot}  winnersToPay: {winnersToPay}");
            // Pay unpaid winners, tip dealer with remainder...
            foreach (var player in winners) if (paidWinners.IndexOf(player) == -1)
            {
                player.chipsRemaining += collectedSidePot / (ulong)winnersToPay;
                if (player.potCommitment <= 0)
                {
                    paidWinners.Add(player);
                    Console.WriteLine($"Player {players.IndexOf(player)} paid out.");
                }
            }
        }
        winners.Clear();
    }

    // Only count potchips for unfolded players. Also prints status to Console.
    public static ulong PotChipsRemaining(List<Player> playersInHand)
    {
        ulong tally = 0;
        foreach (var player in playersInHand) if (!player.folded)
            {
                Console.WriteLine($"Player {players.IndexOf(player)} chips: {player.chipsRemaining}  Commitment: {player.potCommitment} \tHandStrength: {player.handStrength}\tFolded: {player.folded}");
                tally += player.potCommitment;
            }

        foreach (var player in playersInHand) if (player.folded)
                Console.WriteLine($"Player {players.IndexOf(player)} chips: {player.chipsRemaining}  Commitment: {player.potCommitment} \tHandStrength: {player.handStrength}\tFolded: {player.folded}");

        return tally;
    }
}

链接到小提琴

于 2021-10-12T00:45:48.010 回答