【译】21点游戏模拟
原文地址:http://www.codeproject.com/Articles/20176/Blackjack-Game-Simulator
版权:作者版权声明为http://www.codeproject.com/info/cpol10.aspx,可以翻译
简介
这个项目是提供了一个21点的游戏模拟器框架。我想这个应该可以帮助赌徒测试他们听过的策略,过程中我偷巧绕过了一些地方,所以还有很多可以改进的地方,关于21点游戏的规则,可以查询这篇文章。
使用的代码
解决方案包含5个组件
l BlackJack –GUI部分
l Common – 框架使用的通用类、枚举和接口
l Game – 负责执行21点游戏的逻辑部分
l Player - 很简单的电脑玩家
l HumanPlayer -人类玩家简单的接口
组件图
Common组件
Common组件包含下面的内容:
- 牌组类 – 管理牌组
- 手牌类 – 管理玩家的手牌
- IPlayer接口 – 21点玩家接口
- 玩家选项枚举 – 玩家回合可能的设置
- 玩家状态枚举 – 在场上的玩家的状态
- 玩家游戏结束状态 –在游戏结束时候玩家的状态,是赢还是输
- Game组件会用事件通知IPlayer的方法
Game组件
Game组件包括:
- PlayerStatus类 – 对Player的包装类,数据包括当前玩家的手牌和状态
- Game类 – 21点游戏逻辑和控制
- PlayerDirectory类 – 动态加载player类
游戏的简单算法:
- 开始一局新游戏
- 洗牌
- 开始新一轮
- 给每个玩家发2个牌
- 询问每个状态是“玩”的玩家是否还要一张牌,如果回答是,那么再给他们一张牌,如果回答不是,那么就把他的状态改为“standing”
- 重复第5步知道没有玩家是"playing"状态
- 比较玩家的手牌根据游戏规则判定赢家,更新玩家的数据和游戏结束状态。
- 洗牌并把牌放到牌堆里面
- 如果不是最后一轮,跳到第3步
描述的算法是在Round、BeginRound、PlayerTurn、GiveCardToPlayer和EndRound的方法里。可以支持下列事件:
- OnRoundEnd
- OnGameEnd
- OnPlayerAdded
- OnPlayerRemoved
- OnPlayerListCleared
- OnDealerChange
游戏运行在自己的线程并且在回合结束的时候与GUI动画进行同步。在回合结束的时候,游戏线程调用WaitForAnimation并且等待GUI线程动画结束调用AnimationFinished的信号。StartGame,、StopGame、PauseGame和 ContinueGame都用来控制游戏
加载和初始化玩家
PlayerDirectory类负责加载并初始玩家。
其他资源通过LoadPlayer方法加载。为了创建一个Player的实例,调用CreateInstanceOfPlayer方法,声明资源名字和构造参数。
playerDirectory.CreateInstanceOfPlayer("PlayerWithNameAndAge",
new object[]{ "Someone", 30 } );
简单玩家
一个简单玩家有下列逻辑:
- 如果我有黑A, 那我不动
- "I如果我有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, intdealersFirstCard, 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 voidEndRound(PlayerEndGameStatus status,
List dealedCards) { }
public MyPlayer(string name) { _name =name; }
public MyPlayer() { _name ="strange name " +
GetHashCode().ToString(); }
}
}
框架
框架提供了一个简单的方法来测试玩家的逻辑。所有不需要的代码已经去掉了
额外的信息
正如我说过的那样,还有很多提高的空间(比如卡牌应该由一个类表示而不是一个整数,动画效果可以提高)。还有,一些21点的规则没有被实现,比如玩家的分割选项
感兴趣的点
我的室友对于做一个聪明的玩家有了一些兴趣,并且做了一些测试。我希望你也会喜欢。