9

我对游戏开发还比较陌生,所以我决定从头开始创建一个爱好项目,既可以体验又可以娱乐。特定的游戏类似于被称为三张牌吹牛的扑克。该游戏在电影Lock, Stock 和 Two Smoking Barrels中播放。

我一直在阅读一些关于游戏开发的 SO 主题,尽管主要是这个问题。这有助于改进我创建对象的原始方式。

我遇到的一个特殊问题是定义游戏状态。我最初的方法是将所有内容分开(例如将筹码堆放在一个Player类中),但是在阅读了对我之前提到的问题的回答之后,似乎游戏的所有可能状态都应该在一个GameState对象中维护。我想出的基本上是这样的:

abstract class CardGameState
{
    protected List<Player> _Players;
    protected Player _CurrentPlayer;
    protected Dictionary<Player, int> _Chips;
    protected Dictionary<Player, Hand> _CurrentHand;
    protected Dictionary<Player, PlayerStatuses> _PlayerStatus; // PlayerStatuses.InHand, PlayerStatuses.Folded, PlayerStatuses.SittingOut, etc.
    /* etc. */

其中每个CardGameState都通过一些操作进行修改:

public interface IAction
{
    string Name { get; }

    CardGameState Apply(CardGameState state);
    bool IsLegal(CardGameState state);
}

现在我强烈地感觉到这违背了面向对象编程的目的,因为与玩家相关的数据(在这种情况下,是他的筹码堆、手牌和当前状态)没有被Player对象封装。

另一方面,如果玩家加注,我将创建一个RaiseActionthat implements IAction,但接口只接受当前游戏状态,如果筹码堆存储在类IAction中,我认为这不是理想的Player.

基本上,我的问题是:我是否可以两全其美,这样我就可以准确表示游戏状态,同时将所有与游戏状态中的对象特别相关的数据保存在给定对象中?

4

2 回答 2

6

在在线游戏中,使用命令模式(您的 IAction)是标准且经过验证的方法。它不是玩家意义上的面向对象,但动作是面向对象的,所以从纯理论的角度来看,我猜它是一个可靠的设计模式。在实践中,我见过的每一个成功的在线游戏都是这样实现它的,但请注意,动作游戏通常使用非常小的谨慎的动作/数据包,直到它实际上变成一种流。

编辑:

在我回答这个问题很长时间后,我回到这里并意识到这个问题的另一个解决方案是实现 GameState 的 Players、Decks 等......它是从具有Apply(IAction action)成员的IState类派生的。这种方式对象对自己应用动作,而不是让应用程序对对象应用动作,这会将动作和状态映射到访问者模式而不是命令模式。任何一种解决方案都可以工作,visitor 的开销更大,封装更多,而 command 是更简单的解决方案,封装更少。

于 2009-03-03T04:20:45.097 回答
1

似乎您可能为了面向对象而将其面向对象...

看起来像鲍勃马丁的经典保龄球游戏问题。

编辑:-总结-
这是一篇长篇文章,但基本上,通过 TDD 和重构,保龄球评分应用程序从一个包含大量类和多态性的巨大集群变为 20 或 30 行优雅的代码。为什么?因为他们一开始并不真的需要在那里

于 2009-03-03T04:08:55.700 回答