我添加了一条额外的信息,一个折叠的标志。之后,该代码完全可用于解决底池分配问题。我想我基本上使用了 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;
}
}
(链接到小提琴)