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!
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?
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
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With