2009-03-03 102 views
8

我对游戏开发比较陌生,所以决定从头开始为体验和娱乐创建一个业余爱好项目。具体游戏类似于Three Card Brag扑克。本场比赛在电影锁,股票和两个吸烟桶多人纸牌游戏的游戏体系结构和设计策略

我一直在阅读关于游戏开发的一些主题,但主要是this question。这有助于改变我创建对象的原始方式。

我遇到的一个特殊问题是定义游戏状态。我最初的做法是把所有东西都分开(例如把筹码堆放在一个Player类中),但是在阅读了我之前提到的question的回复之后,似乎所有可能的游戏状态都应该保持在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对象封装。另一方面,如果玩家提高赌注,我会创建一个RaiseAction实现IAction,但IAction接口只接受当前的游戏状态,我认为这是不理想的,如果芯片堆栈被存储在Player类中。基本上,我的问题是:我能否拥有两全其美的世界,让我可以精确地表示游戏状态,同时保持与给定对象内的游戏状态内的对象有关的所有数据?

+1

嘿,约翰,我只是在回顾这个问题,并意识到你也可以通过使用访问者模式替换IAction.Apply并使用访问者模式来获得两全其美的好处。现在可能太晚了,但无论如何它可能会作为未来的参考。 – 2009-05-19 03:25:40

回答

6

在使用command-pattern(你的IAction)的在线游戏是标准的,经过验证的方式来做到这一点。从玩家的角度来看,它不是面向对象的,但是这些动作都是面向对象的,所以从纯粹的理论角度来看,它是一种坚实的设计模式。实际情况是,我见过的每一个成功的在线游戏都实现了它,但是请注意,动作游戏通常使用非常小的谨慎行为/包,直到它实际上成为各种各样的流。

编辑:

很长一段时间我回答这个问题后,我就回来了,实现了另一个解决这个问题是执行游戏状态的球员,甲板等..如衍生自IState类与申请(IAction行动)成员。通过这种方式,对象可以将操作应用于自己,而不是让应用程序对对象应用操作,这会将操作和状态映射到visitor-pattern而不是命令模式。任何一种解决方案都可以工作,访问者拥有更大的开销和更多的封装,而命令则是封装更少的简单解决方案。

+0

所以我想这个问题归结为可变性,例如,玩家的名字将驻留在玩家类中,因为它不会受到任何游戏动作的影响。这意味着游戏中可能被任何可能的行动改变的一切都会直接存储在游戏状态中。 – 2009-03-03 04:42:14

1

好像你可能是对象orientizing它面向对象的的缘故......

好像鲍伯马丁的经典bowling game问题。

编辑:-Summary-
其长时间阅读,但基本上,通过TDD和重构,保龄球计分程序,从有很多类和多态性对代码20个或30优雅的线条一个巨大的集群去。为什么?因为他们并不是真的需要在那里

+0

良好的阅读 - 虽然我已经尝试写这个应用程序没有面向对象的行为,我唯一可以挽救的是用于手动比较的类。其余的是控制游戏状态的程序性尝试,并且很容易失去每个玩家动作如何修改它的轨迹 – 2009-03-03 04:28:33