我正在写一个扑克手的HandConverter。这是我的第一个项目,我试图从一开始就做到这一点。
我已经获得了最多的部分,比如球员名单,他们的位置,筹码大小,不同棋盘的牌,正在玩什么游戏等等,但是我很难对投注的表现,特别是不同的加注,投注和来自同一玩家的多个电话。
我发现一些案例,我的天真案例解决方案不起作用,而且它真的很复杂,我不喜欢它。因为它目前适用于NL Hold'em,我想如果我想实现像Stud,Razz等游戏,我会有更多的变通办法,尽管投注结构可能是相同的。
现在我使用此表示形式,我想特别改进Round
和Action
类。你对我有什么建议吗?
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的圆形类?例如
答案 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};
...