我对游戏开发比较陌生,所以我决定从头开始创建一个体验和娱乐的爱好项目。特定游戏类似于称为Three Card Brag的扑克。游戏在电影 Lock,Stock and Two Smoking Barrels 中播放。
我一直在阅读关于游戏开发的一些关于游戏开发的主题,尽管主要是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
类中,我不相信这是理想的。
基本上,我的问题是:我是否可以充分利用这两个世界,以便能够准确表示游戏状态,同时将所有数据专门与游戏状态中的对象保持在给定对象内?
答案 0 :(得分:6)
使用command-pattern(您的IAction)的在线游戏是标准且经过验证的方法。从玩家的角度来看,它不是面向对象的,但是动作是面向对象的,所以从纯粹的理论角度来看,它是一个坚实的设计模式,我想。在实践中,我所看到的每一个成功的在线游戏都实现了它,但请注意,动作游戏通常使用非常小的谨慎动作/数据包,直到它实际上成为各种各样的流。
修改:
在我回答这个问题很长一段时间之后,我回到这里并意识到另一个解决这个问题的方法是实现GameState的玩家,套牌等...来自 IState 类,带有< strong>申请(执行行动)成员。这种方式对象对自己应用操作,而不是让应用程序对对象应用操作,这会将操作和状态映射到visitor-pattern而不是命令模式。这两种解决方案都可以工作,其中访问者具有更大的开销和更多的封装,而命令是更简单的解决方案,封装更少。
答案 1 :(得分:1)
似乎你可能会出于对象的方式对象进行对象化...
看起来像Bob Martin的经典bowling game问题。
编辑: - 总结 -
它是一个很长的阅读,但基本上,通过TDD和重构,一个保龄球评分应用程序从一个具有大量的类和多态的大型集群到20或30个优雅的代码行。为什么?因为他们并不是真的需要首先出现在那里