更好的 C# 扑克框架设计?

发布于 2024-09-15 16:30:20 字数 1200 浏览 3 评论 0 原文

我正在用 C# 编写一个扑克框架,但我不喜欢我目前的设计。我的目标是拥有一个游戏引擎,可以非常快速地以批处理模式让多个 AI 代理相互对战,并让多个 AI 代理与多个人类对战(可能通过 Silverlight 客户端)。我想保持高效率但保持灵活性——例如,它应该能够玩限注德州扑克、无限注德州扑克、限注7张牌梭哈等游戏。

我目前的设计相当笨重, inflexible:

  • HandHistory:包含有关当前手牌的所有信息(玩家参与、下注等)
  • IPlayer:每个玩家都定义一个 GetAction(HandHistory 历史记录) 方法。
  • GameEngine:定义一个返回 HandHistory 对象的 Play(HandInfo info) 方法。
  • PotManager:管理底池并确定每个玩家必须跟注的金额以及他们可以赢得的金额(例如,如果他们的筹码不相等并且全押)。
  • BetManager:管理投注并确定一轮投注何时结束。

HandInfo 类包含有关如何设置手的所有信息。 Play 方法看起来像这样:

HandHistory Play(HandInfo info)
{
    PotManager pots = new PotManager(info);
    BetManager bets = new BetManager(info);
    HandHistory history = CreateHistory(info);

    bets.CollectBlinds();
    if(!bets.GameOver)
    {
        DealHoleCards();
        if(bets.PlayersThatCanStillBet > 1)
            bets.CollectBets();
        if(!bets.GameOver)
        {
            DealFlop();
            ... and on and on
        }
    }

    return history;
}

问题的出现是因为有太多的小事情需要考虑,比如收集盲注等。Pot 和 Bet 管理器类变成了一场噩梦,并且总是充满了错误。此外,我的引擎设计仅支持一种游戏类型(德州扑克),而不支持其他游戏类型。

我的主要排名是效率第一,因为该引擎主要用作数十亿只手的人工智能模拟器。然而,我想有一种更优雅的方式可以做到这一点。

I'm writing a poker framework in C# and I don't like the design I currently have. My goal is to have a game engine that can play multiple AI agents against each other in batch mode very quickly, and play multiple AI agents vs. multiple humans (probably via a Silverlight client). I'd like to keep efficiency high but maintain flexibility-- e.g., it should be able to play games like Limit Hold'em, No-Limit Hold'em, Limit 7-card Stud, etc.

My current design is rather clunky and inflexible:

  • HandHistory: Contains all the information about the current hand (players in, bets made, etc.)
  • IPlayer: Every player defines a GetAction(HandHistory history) method.
  • GameEngine: Defines a Play(HandInfo info) method that returns a HandHistory object.
  • PotManager: Manages the pot and determines how much each player has to call and how much they can win (e.g., if they have unequal stacks and are all-in).
  • BetManager: Manages the bets and determines when a betting round is finished.

The HandInfo class contains all the information about how to setup the hand. The Play method then looks something like this:

HandHistory Play(HandInfo info)
{
    PotManager pots = new PotManager(info);
    BetManager bets = new BetManager(info);
    HandHistory history = CreateHistory(info);

    bets.CollectBlinds();
    if(!bets.GameOver)
    {
        DealHoleCards();
        if(bets.PlayersThatCanStillBet > 1)
            bets.CollectBets();
        if(!bets.GameOver)
        {
            DealFlop();
            ... and on and on
        }
    }

    return history;
}

The problems arise because there are so many little things to consider like collecting the blinds, etc. The Pot and Bet manager classes become a nightmare and are invariably riddled with bugs. Also, my engine design only supports one game type (Hold'em) as opposed to others.

My main ranking is first for efficiency, as the engine is used primarily as an AI simulator over billions of hands. However, I'd like to think there is a more elegant way that this could be done.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

神魇的王 2024-09-22 16:30:20

我的第一个想法是,首先考虑代码的可读性和缺乏冗余,然后优化性能(我认为这就是你所说的效率)。通常很难预见性能瓶颈在哪里,稍微慢一点的应用程序比有错误或无法维护的系统要好。当您准备好优化时,如果您发现它不适合,那么使用 dotTrace 这样的产品很容易还不够快。

关于您添加功能的愿望,我建议您更好地进行重构。这是 TDD 的核心原则之一:编写最少量的代码来完成一项功能,然后重构任何代码异味。通过使用 TDD,您可以确保当您实施 Stud 时,您的 Hold'em 仍然有效。

开始重构的一个好地方是尝试确保每个类都有一个单一的职责(因为听起来您已经遇到了可维护性问题)(SOLID 原则)。您的示例方法有很多职责:投注、发牌、游戏历史记录等。

My first thought is, code for readability and lack of redundancy first, and optimize for performance (which I assume is what you mean by efficiency) last. It is usually hard to foresee where the performance bottle necks will be, and a slightly slower app is better than a buggy or unmaintainable system. It's easy to use a product like dotTrace when you're ready to optimize, if you find it isn't fast enough.

Regarding your desire to add functionality, I recommend becoming better at refactoring. That's one of the core priciples of TDD: write the least amount of code to complete a piece of functionality, then refactor out any code smells. And by using TDD, you can make sure that when you implement, say, Stud, your Hold'em still works.

A good place to start with your refactoring, since it sounds like you are already running into maintainability issues, is to try to ensure each class has a single responsibility (the first of the SOLID priciples). Your example method has many responsibilities: betting, dealing, game history, etc.

鲜血染红嫁衣 2024-09-22 16:30:20

我非常喜欢 John Gietzen 为战舰 AI 锦标赛编写的界面 IOpponent。我会看一下他的框架以获得一些灵感。

什么是最好的战舰人工智能?

哦,我最近看到了这个:
http://visualstudiogallery.msdn。 microsoft.com/en-us/ba4638ad-a2d2-49e5-ae46-94e0f747cae0?SRC=VSIDE

I really liked the interface IOpponent that was written by John Gietzen for the Battleship AI tourney. I would take a look at his framework for some inspiration.

What is the best Battleship AI?

Oh and I recently saw this:
http://visualstudiogallery.msdn.microsoft.com/en-us/ba4638ad-a2d2-49e5-ae46-94e0f747cae0?SRC=VSIDE

赢得她心 2024-09-22 16:30:20

您可以在此处 并在此处进一步解释。这可能会对您的性能有所帮助。欢迎通过其中的电子邮件地址提供所有反馈。

An example of a ready made Texas Hold'em 7- and 5-card evaluator can be found here and further explained here. This might help you with performance. All feedback welcome at the e-mail address found therein.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文