2013-11-28 471 views
2

我目前正在创建一盘棋,由以下类:国际象棋游戏的设计和Singleton模式

  • ChessPiece - 对于所有不同的棋子,用MovementBehaviour实例变量
  • MovementBehaviour组成 - 由PawnMovementBehaviour实现的接口, KingMovementBehaviour等类定义 如何移动每个块类型
  • 器ChessBoard - 与像addPiece()/ removePiece()功能的ChessPiece [] [] 2D阵列由......组成/ replacePiece()等
  • 播放 - 小类有助于关联哪个片属于哪个演奏人
  • 游戏 - 主要的课程首先要询问玩家的名字和想要的棋子颜色,然后通过实例化棋盘并让玩家移动转过 转到达到将军。

我想知道如果我应该使用Singleton模式(关于ChessBoard类)?目前我不是,我正在将棋盘的实例传递给棋子移动功能,以便棋子可以理解其周围环境。这是因为当然移动被认为是合法的,这取决于任何时候在棋盘上占用/空的空间。

+4

当涉及到典当时,注意MovementBehaviour:en-passant取决于对手的previoius移动。 Castling需要考虑其他因素(不能通过检查进行城堡检查,这两件棋子都不得在castling之前移动)。如果我是你,我不会选择单身。把棋盘作为每件棋子的父对象似乎对我来说是合理的。 – Bathsheba

+1

你希望从Singleton模式中获得什么?如果有的话,您的设计的灵活性和一致性会产生什么样的成本? – GaryF

回答

3

单身很少是一个好主意。我最近刚刚开始了一个类似的项目,所以我会从我目前的经验中回答这个问题。

我实现的方式是通过考虑棋盘Location对象,其中一个位置持有X - 值,Y - 值的集合和Piece对象。只有相关的地方填写空的地方甚至没有被跟踪。

你似乎想知道你是否应该使用单例作为验证的单一目的。移动完成后,您需要验证许多许多事情:您可以这样移动吗?你检查?它是否和谐?这是一个rochade?等等。

你可以做的是创建一组验证方法,它们将棋盘和起始和终止位置作为参数。通过这种方式,您可以获得检查移动是否有效所需的全部信息。这确实需要件知道他们自己的属性:我该如何移动?我的颜色是什么?

当你有这一切,你可以实现不同的验证逻辑来​​移动。

使用单例将是相当讨厌的,当你可以提取验证并通过棋盘周围。测试也会更加困难(并且好的测试绝对是你想在棋类游戏中找到的东西)。

我的设置是这样的:

Chessboard.CanMoveToLocation(int startX, int startY, int endX, int endY) { 
    // Call validators with local field chessboard and given location objects 
} 

每个验证将返回一个自定义枚举ValidationResult以表明它是否允许或禁止这种特殊的验证。

您必须确保以正确的顺序调用验证器(在检查它是否为有效的移动后返回错误不是一个好主意:他可能一直在rochading或杀死en-passant)。或者你可以结合相关的验证器。

如果您想查看:my current (far from finished) implementation

1

以我的经验,我宁愿在这种情况下使用观察者模式。 ChessBoard类扮演Observer的角色,ChessPiece应该是一个抽象类,它是Subject类。您可能需要查看观察者模式及其用法

当您拿一块棋子进行移动时,这意味着该棋子的位置已被更改,棋子会通知棋盘检查移动是否它是否有效。