简体   繁体   中英

Chess game design and Singleton pattern

I am currently creating a chess game consisting of the following classes:

  • ChessPiece - For all the various chess pieces, composed with a MovementBehaviour instance variable
  • MovementBehaviour - Interface implemented by PawnMovementBehaviour, KingMovementBehaviour etc classes to define how each piece type moves
  • ChessBoard - Consisting of a ChessPiece[][] 2D array with functionality like addPiece()/removePiece()/replacePiece() etc
  • Player - Small class helps associate which pieces belong to which human player
  • Game - The main class essentially which will begin by asking players for their names and desired piece colors and then running the game by instantiating a ChessBoard and letting players move turn by turn until checkmate is reached.

I was wondering if I should be using a Singleton pattern (With regards to the ChessBoard class) ? Currently I am not and I am passing the instance of the ChessBoard into the chess pieces movement functionality so that the piece can understand its surroundings. This is because of course moves are deemed legal depending on what spaces are occupied/empty on the board at any time.

Singletons are very rarely a good idea. I happen to have started a similar project recently so I will answer this from my current experience.

The way I've implemented it is by considering a chessboard a collection of Location objects, where a location holds an X -value, Y -value and a Piece object. Only relevant places are filled in where empty ones aren't even tracked.

You seem to be wondering if you should use a singleton for the single purpose of validation. There are many, many things you have to validate when a move is done: Can you move that way? Are you check? Is it en-passant? Is it a rochade? etc.

What you could do is create a bunch of validate methods that take as arguments a chessboard and the start- and endlocation. This way you have all information required to check if the move is valid. This does require the pieces to know their own properties: how can I move? What's my color?

When you have all this, you can implement the different validation logic to make a move.

Using a singleton will be rather nasty when you could just extract the validation and pass the chessboard around. It would also be much harder to test (and good testing is definitely something you want in a chessgame).

My setup looks like this:

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

Each validator will return a custom enum ValidationResult to indicate if it's allowed or forbidden for this particular validator.

You'll have to make sure the validators are called in the correct order (returning false after checking if it's a valid move is not a good idea: he might have been rochading or slaying en-passant). Or you could ofcourse combine related validators.

Should you wish to take a look: my current (far from finished) implementation .

In my experience, I'd rather use Observer Pattern in this case. The ChessBoard class plays the role of Observer and the ChessPiece which should be an abstract class is the Subject class. You might want to make a look on Observer Pattern and it usage

When you take one Piece and make a movement, that means the location of that Piece has been changed and the Piece will notify to the board to check the movement whether it is valid or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM