Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing a flexible and extensible bonus system for a Scrabble's game implementation

Let's say I'm implementing my own version of Scrabble. I currently have a Board class that contains lots of Squares. A Square in turn is composed of a IBonus and a Piece. The bonus implementations are actually the usual bonus for Scrabble, but it is possible that I might try to add some new and twisted bonus to spice the game -- flexibility here is paramount!

alt text

After thinking for a while I came to the conclusion that for IBonus implementations to work, they'll need to know the whole Board and also its current position(on the Board, so it knows where it is and it can check for the piece that's in the same square as the bonus is). This strikes me as bad as basically it needs to know a whole lot of information.

So, my naive implementation would be to pass the Board as argument to IBonus.calculate() method, IBonus.calculate(Board board, Point position), that is.

Also, it seems to create a circular reference. Or am I wrong? alt text

I don't particulary like this approach, so I am looking for other possible approaches. I know I can make calculate accept an interface instead of a concrete class, i.e., calculate(IBoard board) but I IMO that isn't all that better than the first case.

I fear being too focused on my current implementation to be able to think of whole different designs that could fit at least as well as solutions to this problem. Maybe I could re-architect the whole game and have the bonuses in other place, so it would facilitate this calculation? Maybe I am too focused on having them on the Board? I certainly hope there are other approaches to this problem out there!

Thanks

like image 884
devoured elysium Avatar asked Oct 25 '10 21:10

devoured elysium


3 Answers

I assume Board has the visible state of the game, and there would be other objects such as Rack (one per Player,) and a DrawPile.

"Double Score if word contains a real (non-blank) Z" - would require you pass in the Word, or the Board and the position of the word.

"Double Score if the word is the longest on the board" requires the entire Board.

"Double Score if the first letter of the word matches a randomly selected letter from the DrawPile" requires the DrawPile of course.

So to me it just depends on the rules you implement. I'd be comfortable with passing Board to the IBonus score() implementation.

edit - more thoughts.

So a board has 17x17 squares, or whatever. I'd assign an IBonus implementation to each square of the board (there would be an implementation called PlainEmptySquare that was inert.) You'd only need to instantiate each implementation of IBonus once - it could be referenced many times. I'd probably take the low road and instantiate each one explicitly, passing in the arguments needed. If one type needs the Board, pass it in. If another needs the DrawPile, pass it in. In your implementation, you'd have perhaps 12 lines of ugliness. /shrug

like image 111
Tony Ennis Avatar answered Oct 21 '22 07:10

Tony Ennis


Something like the following might work:

CurrentGame has a Board, which has a collection of Squares. A Square could have an IBonus, however there is no Calculate() method on a Square. A Square may have a Piece, and a Piece may have a Square (ie a square may or may not be empty, and a piece may or may not have been placed on the board).

Board also has a calculateScoreForTurn() method which would accept a collection of Pieces representing the pieces that have just been placed on the board for that turn. Board knows all the information about the pieces and squares that have just been placed, as well as the surrounding or intersecting pieces and squares (if applicable) and thus has all the information required to calculate the score.

like image 1
jwaddell Avatar answered Oct 21 '22 09:10

jwaddell


This strikes me as bad as basically it needs to know a whole lot of information

I think it's necessary. You're just passing a reference to the board, not actually causing large quantities of data to be moved around.

like image 1
Kevin Stricker Avatar answered Oct 21 '22 08:10

Kevin Stricker