多人卡牌游戏的游戏架构和设计策略

发布于 2024-07-14 08:45:49 字数 1531 浏览 6 评论 0原文

我对游戏开发比较陌生,所以我决定从头开始创建一个业余爱好项目,以体验和娱乐。 具体游戏类似于扑克,称为三牌吹牛。 该游戏在电影《锁、枪托和两个大烟桶》中进行过。

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

我遇到的一个特殊问题是定义游戏状态。 我最初的方法是将所有内容分开(例如将筹码堆栈保留在 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 对象封装。

另一方面,如果玩家要加注,我将创建一个实现 IActionRaiseAction,但仅 IAction 接口接受当前的游戏状态,如果筹码堆栈存储在 Player 类中,我认为这并不理想。

基本上,我的问题是:我能否两全其美,以便能够准确表示游戏状态,同时将与游戏状态中的对象相关的所有数据保留在其给定对象内?

I am relatively new to game development so I decided I wanted to create a hobby project from scratch for both experience and entertainment. The specific game is similar to poker known as Three Card Brag. The game is played in the movie Lock, Stock and Two Smoking Barrels.

I have been reading up on some of the topics on SO regarding game development, though mostly this question. This has helped revamp the original way I was creating the objects.

One particular problem I am having is defining game state. My initial approach was to separate everything (e.g. keeping chip stacks inside a Player class) but after reading the responses to the question I mentioned previously, it seems as though all possible states of the game should be maintained within a GameState object. What I came up with is essentially this:

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. */

where each CardGameState is modified by some action:

public interface IAction
{
    string Name { get; }

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

Now I'm feeling very strongly that this is defeating the purpose of object-oriented programming, because the data specifically related to the player (in this case, his chip stack, hand, and current status) is not encapsulated by the Player object.

On the other hand, if a player were to raise the bet, I would be creating a RaiseAction that implements IAction, but the IAction interface only accepts the current game state, which I don't believe would be ideal if the chip stacks were stored within the Player class.

Basically, my question is: can I have the best of both worlds such that I can have an exact representation of the game state while simultaneously keeping all data related specifically to an object within the game state inside its given object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

少年亿悲伤 2024-07-21 08:45:49

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

编辑:

在我回答这个问题很长一段时间后,我回到这里并意识到这个问题的另一个解决方案是实现 GameState 的玩家、套牌等......源自 IStateApply(IAction action)成员的strong>类。 这样,对象对自身应用操作,而不是让应用程序对对象应用操作,这会将操作和状态映射到 访问者模式而不是命令模式。 任何一种解决方案都可以工作,其中访问者具有更大的开销和更多的封装,而命令是更简单的解决方案,封装更少。

In online-games using the command-pattern (your IAction) is the standard, and proven, way to do it. It's not Object Oriented in the sense of the player, but the actions are Object Oriented, so from a purely theoretical point of view its a solid design pattern, I guess. And in practice thats how every successful online game I've seen implements it, but note that action games normally use very small discreet actions/packets, until it practically becomes a stream of sorts.

Edit:

A long time after I answering this, I came back here and realized another solution to this problem is to implement GameState's Players, Decks, etc... as derived from an IState class with an Apply(IAction action) member. This way objects apply actions on themselves, instead of having the application apply actions on objects, this would map actions and state to a visitor-pattern instead of a command pattern. Either solution will work, where visitor has the larger overhead and more encapsulation, while command is the easier solution with less encapsulation.

起风了 2024-07-21 08:45:49

看起来你可能是为了面向对象而面向对象......

看起来像鲍勃·马丁的经典

编辑:-摘要-
读起来很长,但基本上,通过 TDD 和重构,保龄球评分应用程序从具有大量类和多态性的巨大集群变成了 20 或 30 行优雅的代码。 为什么? 因为他们一开始其实并不需要在那里

Seems like you might be Object-orientizing it for Object-orient's sake...

Seems like Bob Martin's classic bowling game problem.

EDIT: -Summary-
Its a long read, but basically, through TDD and refactoring, a bowling scoring application went from a huge cluster with lots of Classes and polymorphism to 20 or 30 elegant lines of code. Why? Because they didn't really need to be there in the first place

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文