Re: Design decision for a game
On May 23, 12:17 am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
On Thu, 22 May 2008 13:28:37 -0700, pek <kimwl...@gmail.com> wrote:
[...]
OK.. I think I understand some things here. I won't be fancy, so
threshold is a little overkill (although I did like the idea). What I
see problematic here is this:
class House {
...
public void addCard(Card card) {
// do some things, or probably nothing because the rules would
take care of it
...
// inform listeners
for (HouseListener lstnr : listeners) {
lstnr.cardAdded(this, card);
}
}
...
}
That part seems fine, as far as it goes.
class SixCardsRule implements HouseListener {
...
public void cardAdded(House house, Card card) {
if ( house.getCards().size() == 5 ) {
// then adding this card satisfies this Rule. So,
house.setCards(new ArrayList<Card>());
// Now notify everyone. The 50 is for the score to be added
for (RuleListener lstnrs : listeners) {
lstnrs.ruleSatisfied("Six cards in total",50);
}
}
}
...
}
This part I'm not so sure of.
Without seeing your whole architecture, it's hard to say for sure. But it
seems to me that someone other than the Rule should be maintaining the
score. I'm not sure if this is the House, or if you have some other class
that's the entire Game. But it seems to me that the Rule should not
necessarily be raising score-change events itself, but rather should be
calling some method somewhere that adds 50 points to the score. Objects
that need to be notified of score changes would be attached as a listener
to _that_ object.
Correct, I forgot to mention that indeed I do have a different class
that handles the game logic called Engine. It contains an int for the
game's score.
Now, if you _also_ want to provide for notification of when a specific
rule is satisfied, your Rules could allow those listeners to be added.
And they would be notified much as you show above. Except that the score
would not necessarily be part of the method parameters, at least not in my
view.
Alternatively, if you _do_ want the Rule notifications to include the
score, then either _all_ rule-satisfying conditions should affect the
score, or you need to expand your RuleListener interface so that there are
different methods, some of which include a point total to be added to the
score, and others that don't. Or perhaps you provide just one method in
the interface that is the "score changed" notification", and that's sent
separately from other notifications, like "rule satisfied".
Any of these could work. Which is "best" is hard to say. For my tastes,
I'd prefer either the first suggestion or the last. If you intend for
there only to ever be a single scoring object, then the first might be
more appropriate. Then each Rule would have to know which object was that
single scoring object and would directly call a method on that object to
update the score.
On the other hand, if you want your design to be more flexible, such that
you can have multiple scorers present, then it probably makes more sense
for the Rules to use the RuleListener interface to report score changes.
Each scoring object can then subscribe as appropriate to the rules
relevant for that scoring object.
I am thinking about implementing online support, but currently I'll
stick to the single player. I think I don't have time. I'll keep this
in mind though.
As an example of this, consider something like (following your previous
listener interface pattern...you may want to consider instead following
the usual Java model, where an "Event" class is defined that includes all
of the relevant data, including the source and the specifics of the event):
public interface RuleListener
{
void ruleSatisfied(Rule sender, string ruleName);
void scoreChange(Rule sender, int points);
}
This sounds interesting. I'll totally give it a try.
Then scoring objects can subscribe to the Rules as needed, and the UI and
other interested objects can also subscribe. If it turns out that there's
little or no overlap between these two types of subscribers, you might
even break the interface into two, with one interface dedicated to things
that are just "activity notification" sorts of things, and the other
dedicated to things that actually change the game state. Often one event
from each might be raised, but only objects of the appropriate
functionality would subscribe to the specific listener group. That way
you don't waste a lot of time having, for example, having UI objects
receiving and ignoring notifications for game state changes, and having
game state objects receiving and ignoring notifications for UI events.
Yes, there should be two types of interfaces.
I think ultimately I'd go with _some_ variation on this last approach
(that is, the one where the Rule supports listeners for events separated
into appropriate categories, whether in the same interface or in two or
more), but any of the above would probably work (including what you
posted, if you really want to do it that way).
By the way, I'm not sure that the House should expose the collection
implementation. That is, rather than a "setCards" method that takes the
actual collection, it probably makes more sense to have a "clearCards"
method that resets the internal implementaton. If you really need a way
to add or set multiple cards at once from a non-empty collection, you
could still have a more general-purpose method that takes a List<Card>
instead of some specific collection type.
Yeap, I totally agree. I added clearCards().
Pete