Question

I am making a tiny game app in my free time, and I have just recently hit a wall.

The idea is that there is a fixed grid of Boxes available and that many Jewels as well.

Both boxes and jewels can come in different colors. As with color space, the three basic type of boxes are Red, Yellow and Blue. The other ones available are, of course, Orange, Purple, Green, with a special White box.

I also have the Jewels, which correspond to the same colors as boxes.

Now, the logic is as following:

  • Primary color boxes will give reward only if they contain a gem whose color is the same as the box color or is made from the box color
    • For example, red box will give bonus if there is a red, orange or purple jewel inside it because of the following
      • Red is made of Red
      • Orange is made of Red and Yellow
      • Purple is made of Red and Blue
      • White is made of Red, Blue and Yellow
    • Red box won't give any bonus for Green jewel, because Green is Blue and Yellow and there is no Red in there
  • Secondary color boxes cannot accept any of the primary color jewels because secondary color boxes are made of at least two colors, while primary gems are made of 1 color only.
    • Given that, secondary color boxes can only accept the corresponding color jewel, plus the white one.
  • And as an exception to the rules above, white box is like a bonus box, which can accept all jewels

I'm puzzled with how to make the domain model for this so it doesn't contain (or contains as least as possible) ifs and instanceofs.

Also, if I would like to extend the types of boxes and jewels one day, I'd like it to be done in any of the following two ways by adding new classes without having to change old ones.

Was it helpful?

Solution

I imagine you could have something like this:

public enum Color {

    RED(true),
    YELLOW(true),
    BLUE(true),
    ORANGE(false),
    PURPLE(false),
    GREEN(false),
    WHITE(false);

    static {
        ORANGE.components.add(RED);
        ORANGE.components.add(YELLOW);

        PURPLE.components.add(RED);
        PURPLE.components.add(BLUE);

        GREEN.components.add(YELLOW);
        GREEN.components.add(BLUE);

        WHITE.components.add(RED);
        WHITE.components.add(YELLOW);
        WHITE.components.add(BLUE);    
    }

    private boolean primary;
    private List<Color> components;

    Color(boolean primary) {
        this.primary = primary;
        this.components = new ArrayList<Color>();
    }

    public boolean isPrimary() {
        return primary;
    }

    public Set<Color> components() {
         return Collections.unmodifiableSet(this.components);
    }
}

Then you can have something like this:

public class Jewel {
    private Color color;

    ...
}

public class Box {
    private Color color;
    private Jewel jewel;

    ...
}

All the score calculation can be done inside a scoring service of some kind:

public class ScoringService {

    public int calculate(Box box) {
        int score = 0;
        Jewel jewel = box.getJewel();

        if(box.getColor() == jewel.getColor() || box.getColor() == Color.WHITE) {
            score++;
        }

        if(!box.getColor().isPrimary() && jewel.getColor() == Color.WHITE) {
            score++;
        }    

        if(box.getColor().isPrimary() && !jewel.getColor().isPrimary()) {
            Set<Color> intersection = new HashSet<Color>(box.getColor().components());
intersection.retainAll(jewel.getColor().components());
            score += intersection.size();
        }

        return score;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top