I've been working on a project that is very data-driven (a checkers board game with customizable rules; I'm using XML for the data storage). I need a design that is easy to extend as we add new features to the project via new XML tags.
My XML schema looks like this for a win condition (checkers):
<game>
<winconditions>
<condition winner="Black">
<Pieces color="Red" number="0" />
</condition>
<condition winner="Red">
<Pieces color="Black" number="0" />
</condition>
</winconditions>
</game>
<game>
is the root element. There are other major sections such as <board>
which defines the size and shape of the board and placement of the pieces, and <moves>
which defines how pieces move. The idea is to have several "options" that combine to form a "condition" - if all "options" are true, the "condition"'s evaluation returns a winner.
Right now, the best strategy I have come up with is to create a package for the tag processing classes:
processors
pieces
And an interface to a win condition option:
public interface WinConditionOption {
void setParameters(HashMap<String, String> args);
boolean evaluate(GameState state);
}
The file processor, when it sees a tag inside the <winconditions>
tag, uses reflection to look up the corresponding class and calls it using the interface. So the Pieces
tag causes a Pieces
object to be created and setAttributes()
is called with the tag's attributes. When we check for a win, evaluate()
is called with the current state of the game. Pieces
would evaluate whether the number of pieces belonging to that player was a certain number, 0 in this case (no pieces left).
Is this a good design? Is there a better way to do it and still be able to write minimal new code to add a new win option?