65.9K
CodeProject 正在变化。 阅读更多。
Home

二十一点游戏模拟器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.26/5 (9投票s)

2007年8月24日

CPOL

3分钟阅读

viewsIcon

80956

downloadIcon

5507

二十一点游戏模拟框架

Screenshot - blackjack.png

引言

该项目提供了一个 Blackjack 游戏模拟器的框架。我不知道这是否会有用……嗯,对于赌徒来说,测试他们听说过的策略可能会有用。我有一个演示要做,所以我就胡乱拼凑了一个,最后得到了这个,所以还有很多地方需要改进。有关 Blackjack 游戏和规则的更多信息,可以参考 维基百科的文章

Using the Code

解决方案包含五个组件

  • BlackJack - GUI 应用程序
  • Common - 框架使用的通用类、枚举和接口
  • Game - 负责 Blackjack 游戏逻辑的组件
  • Player - 非常简单的计算机玩家
  • HumanPlayer - 人类玩家的简单接口
Screenshot - app.png
图:组件图

通用组件

通用组件包含

  • Deck 类 - 管理牌堆
  • Hand 类 - 管理玩家的手牌
  • IPlayer 接口 - Blackjack 玩家的接口
  • PlayerOptions 枚举 - 玩家回合中的可能选项
  • PlayerInGameStatus 枚举 - 当前玩家状态(玩或停牌)
  • PlayerEndGameStatus 枚举 - 游戏结束时的玩家状态(赢家、输家……)

Game 组件调用 `IPlayer` 的方法来通知玩家事件。

游戏组件

游戏组件包含

  • PlayerStatus 类 - 玩家的包装类;此类存储玩家当前手牌和当前状态等数据,以防止作弊 :)
  • Game 类 - Blackjack 游戏逻辑和控制
  • PlayerDirectory 类 - 动态加载玩家组件

游戏的简化算法

  1. 开始新游戏
  2. 洗牌
  3. 开始新一轮
  4. 给所有玩家发两张牌
  5. 询问所有状态为“玩”的玩家是否想要另一张牌:如果有人想要,就再给他们发一张牌;如果有人不想要,就将其状态改为“停牌”。
  6. 当还有状态为“玩”的玩家时,重复步骤 5。
  7. 根据游戏规则比较玩家的手牌以宣布赢家和输家,更新玩家统计数据和游戏结束状态。
  8. 洗牌,发牌并将牌放回牌堆末尾。
  9. 如果这不是最后一轮,跳转到步骤 3。

上述算法在 `Game` 类的 `Round`、`BeginRound`、`PlayerTurn`、`GiveCardToPlayer` 和 `EndRound` 方法中实现。可以通过事件(`Game` 类的成员)来观察游戏。

  • OnRoundEnd
  • OnGameEnd
  • OnPlayerAdded
  • OnPlayerRemoved
  • OnPlayerListCleared
  • OnDealerChange

游戏运行在自己的线程中,并提供与 GUI 动画同步的方法,动画在每轮结束后播放。在每轮结束时,游戏线程调用 `WaitForAnimation`,直到 GUI 线程通过调用 `AnimationFinished` 发出动画完成的信号。`StartGame`、`StopGame`、`PauseGame` 和 `ContinueGame` 方法用于控制游戏。

玩家的加载和实例化

`PlayerDirectory` 类负责加载玩家组件和实例化玩家。在类的构造函数中,会检查 `.\Players` 文件夹中的所有程序集,如果包含玩家类,则会加载它们。玩家类的名称必须是 `MyPlayer`,并且必须在 `Player` 命名空间中。

可以通过调用 `LoadPlayer` 方法并指定程序集路径来添加其他程序集。要创建玩家的实例,只需调用 `CreateInstanceOfPlayer`,并根据需要指定程序集名称和构造函数参数。

playerDirectory.CreateInstanceOfPlayer("PlayerWithNameAndAge",
    new object[]{ "Someone", 30 } );

简单玩家

具有简单逻辑的简单玩家

  • “如果我有 Blackjack,我就停牌”
  • “如果我有点数 21,我就停牌”
  • “如果我的点数大于等于 17,我就停牌”
  • “如果我的点数小于 17,我就再拿一张”

……可以用几行代码实现。

using Common;
namespace Player
{
    public class MyPlayer : IPlayer
    {
        private Hand _myHand = new Hand();

        private string _name;
        public string Name { get { return _name; } }

        public void NewRound(bool newGame, 
            bool isDealer, int dealersFirstCard, int numberOfDecks)
        { _myHand.Restart(); }

        public PlayerOptions Turn(int left)
        {
            if (_myHand.IsBlackJack || _myHand.Values.Contains(21))
                return PlayerOptions.Stand;

            return _myHand.Values[0] <= 
                17 ? PlayerOptions.Hit : PlayerOptions.Stand;
        }

        public void GiveCard(int card) { _myHand.Add(card); }

        public void EndRound(PlayerEndGameStatus status, 
            List<int> dealedCards) { }

        public MyPlayer(string name) { _name = name; }

        public MyPlayer() { _name = "strange name " + 
            GetHashCode().ToString(); }
    }
}

框架项目

框架项目提供了一种便捷的方式来测试玩家逻辑,并配有完整的环境和项目设置。所有不必要的源代码都已删除。

附加信息

正如我所说,还有很多改进的空间(例如,牌应该由类而不是整数表示,动画代码可以改进)。此外,一些 Blackjack 规则尚未实现,例如玩家的分牌选项。

关注点

嗯,我的大学同学在制作更聪明的玩家方面玩得很开心,还举行了一点比赛。希望你也会喜欢。

历史

  • 2007 年 8 月 24 日 -- 原文发布
© . All rights reserved.