在扑克中下注轮次的对象表示

时间:2009-11-18 18:13:17

标签: c# oop class-design poker

我正在写一个扑克手的HandConverter。这是我的第一个项目,我试图从一开始就做到这一点。

我已经获得了最多的部分,比如球员名单,他们的位置,筹码大小,不同棋盘的牌,正在玩什么游戏等等,但是我很难对投注的表现,特别是不同的加注,投注和来自同一玩家的多个电话。

我发现一些案例,我的天真案例解决方案不起作用,而且它真的很复杂,我不喜欢它。因为它目前适用于NL Hold'em,我想如果我想实现像Stud,Razz等游戏,我会有更多的变通办法,尽管投注结构可能是相同的。

现在我使用此表示形式,我想特别改进RoundAction类。你对我有什么建议吗?

public class HandHistory
{
    public GameInfo GameInfo;
    public TableInfo TableInfo;
    public List<Player> Players;
    public List<Round> Rounds;
    public string rawtext;
    public bool withHero;

}

public Round
{
    public List<Action> Action;
    public string Name;
    public decimal Potsize;
    public ulong Cards; //usually would have used a custom class, 
                        //but I need them in a ulong mask for some library I use
}

public class Action
{
    public Player Player;
    public string Type;
    public decimal Amount;
}

P.S。我也使用List来存储不同轮次,是否有更好的方式来继承Flop,Turn和River的圆形类?例如

6 个答案:

答案 0 :(得分:2)

您可以使用枚举:

而不是Action.Type的字符串
enum BettingAction
{
   Check,
   Bet,
   Call,
   Raise,
   Fold
}

答案 1 :(得分:1)

当你说第一个项目是什么意思?我猜你是学生或者是编程新手。

根据这个假设,我建议选择一些比扑克手历史更简单的东西。就像在游戏编程中一样,想到你创建最新的使命召唤游戏的第一个游戏编程是不合理的。你从突破开始,然后从那里向上移动。

如果你不想小于我的建议,请不要跳入编码。当你这样做时,你将花更多的时间来旋转你的车轮,而不是完成任务。

例如,你应该首先花时间设计你的程序将做什么以及它不会做什么。尽量做到尽可能完整。这可以通过使用UML程序或像笔和纸一样简单的东西来完成。

我会想出你想要一只手进步的方式。您要跟踪的信息。一旦你真正理解了这一点,你的数据结构就会开始变得生动。

由于您不熟悉编程,我将开始编写概念验证代码。然后将其移至最终项目。我所说的概念验证是代码,你只是在测试一个想法,看它是如何工作的。例如,手工历史如何运作?你能创建一些“模拟”历史并设置它们吗?理想情况下,你会进行单元测试,但让我们开始小一些。

重要的是要知道你正在构建一个程序,就像一个房子。你需要知道你想要它做什么而不做(蓝图)。每一步是什么。而你慢慢地建立其他作品。这是一个需要时间的过程,但最终还是值得的。

答案 2 :(得分:0)

卡可以有更好的名字,但我假设你的意思是社区卡。我会把它作为卡片列表,然后转弯和河流子类只会在列表中有一张卡片。我还建议以对您有意义的方式表示卡片,然后在需要与库进行交互时进行转换。

答案 3 :(得分:0)

不是一个与编程相关的答案;但是Razz或Stud的投注风格与Hold'em在几个方面不同。

1。)没有百叶窗;相反的是 2.)开场的人可以带入或完成投注 3.)有更多轮次的投注

你有一个很好的开始。您可能想要创建一个List<Hands>,其中包含List<Rounds>。否则你将有一个巨大的轮次列表,但无法判断一只手的开始/结束时间和另一只手的开始。

我认为你可能需要定义你的动作类型,然后事情可能会开始落实到位。以下是我对类型的看法:

检查
投注
折叠
呼叫
提升(基本上是一个电话和下注)

可能还想考虑在你的动作类上实现类似“先行动作”的东西;因为每个玩家都对他们面前的动作作出反应。

你也想要解决游戏的一些细微差别;玩家下注500,玩家b全押250;因为除了在这种情况下,呼叫需要匹配先前的赌注。

答案 4 :(得分:0)

圆形一词有点含糊不清。 BettingRound让它变得更加明显。 我觉得这里不需要卡片,名字和盆栽。 Potsize是整个下注轮中的动作和变化的函数。 座位代表游戏比玩家列表更好,因为这可以让你更明显地表示游戏状态(堆栈大小等)。 我没有看到需要翻牌,河牌被明确分配给轮次 - 只需使用卡片列表和一些约定。例如前三张牌=翻牌......第一轮下注=翻牌圈。使用一些扩展方法以方便引用holdem的翻牌。 当您需要使用它时,可以通过转换使用ulong版本的卡,而不是使您的域模型混乱。

这就是我如何看待特定个人游戏的模型(即1翻牌,河牌,转牌等)。对所有游戏进行建模还有很多工作要做(例如限制游戏使用小赌注/大赌注而不是盲注来定义赌注)。

公共类卡     {         公共套装;         公共等级排名;         public ulong ToCardMask();     }

public enum Suit
{
    Clubs,
    Diamonds,
    Hearts,
    Spades
}

public enum Rank
{
    Ace,
    Deuce,
    Trey,
    //...
    Jack,
    Queen,
    King
}

public class Game
{
    public GameInfo GameInfo;
    public TableInfo TableInfo;
    public List<BettingRound> BettingRounds;
    public List<Card> CommunityCards;
    public string Rawtext;
    public bool WithHero; //??
}

public static class GameExtensions
{
    public static BettingRound Flop(this Game game)
    {
        return game.BettingRounds[0];
    }

    public static List<Card> FlopCards(this Game game)
    {
        return game.CommunityCards.Take(3).ToList();
    }
}

public class GameInfo
{
    public GameType GameType;
    public GameBettingStructure BettingStructure; // Limit, PotLimit, NoLimit
    public Stakes Stakes; // e.g. { $1, $2 }
    public long Id;
    public List<Seat> Seats;
}

enum GameType // prob change to a class for extensibility
{
    HoldEm,
    Razz,
    StudHi,
    StudHiLo,
    OmahaHi,
    OmahaHiLo
}

enum GameBettingStructure
{
    Limit,
    PotLimit,
    NoLimit
}

class Stakes // probably needs some tweeking for stud games (e.g. bring-in ...)
{
    public Money Ante;
    public List<Money> Blinds;
}

public class Seat
{
    public Player Player;
    public Money InitialStackAmount;
    public Money FinalStackAmount; // convienience field can be calculated
    public List<Card> Hand;
}

class Money
{
    public decimal Amount;
    public Unit Unit;
}

enum Unit
{
    USD,
    EUR,
    AUD,
    TournamentDollars
}

public class Player
{
    public string Name;
}

public class TableInfo
{
    public string Name;
}

public class BettingRound
{
    public List<BettingAction> BettingActions;
}

public class BettingAction
{
    public abstract Money PotSizeAfter();
    public byte SeatNumber;
}

public class Fold : BettingAction { }
public class Call : BettingAction { }
public class BringIn : BettingAction { }
public class Complete : BettingAction { }
public class Bet : BettingAction
{
    public Money Amount;
}

public class Raise : Bet { }

答案 5 :(得分:0)

而不是SubClassing Round到FlopRound TurnRound等,我会在round中使用Street属性,也在Action中使用。

static public enum Street {PREFLOP,FLOP,TURN,RIVER};

...