package jrummikub.model; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import sun.reflect.generics.reflectiveObjects.NotImplementedException; import jrummikub.util.Pair; /** Class managing {@link Stone}s joined together to form sets */ public class StoneSet implements Iterable, Sizeable { float border = 0.125f; private List stones; public StoneSet(Stone stone) { stones = Collections.singletonList(stone); } public StoneSet(List stones) { this.stones = new ArrayList(stones); } /** Test for rule conflict within the StoneSet */ public boolean isValid() { if (stones.size() < 3) { return false; } int nonJoker1 = -1, nonJoker2 = -1; for (int i = 0; i < stones.size(); i++) { if (stones.get(i).isJoker()) { continue; } nonJoker2 = nonJoker1; nonJoker1 = i; } if (nonJoker2 == -1) { return true; } // is run if (stones.get(nonJoker1).getColor() == stones.get(nonJoker2) .getColor()) { return isValidRun(nonJoker1); } // is group else { return isValidGroup(); } } /** * Test for rule conflict within the StoneSet, assuming we have a run * * @param referencePosition * position of stone used as reference (any non-joker stone) */ private boolean isValidRun(int referencePosition) { StoneColor runColor = stones.get(referencePosition).getColor(); int startValue = stones.get(referencePosition).getValue() - referencePosition; int endValue = startValue + stones.size() - 1; if (startValue < 1 || endValue > 13) { return false; } for (int i = 0; i < stones.size(); i++) { if (stones.get(i).isJoker()) { continue; } if (stones.get(i).getColor() != runColor) { // warum macht er das nicht? return false; } if (stones.get(i).getValue() != i + startValue) { return false; } } return true; } /** * Test for rule conflict within the StoneSet, assuming we have a group */ private boolean isValidGroup() { if (stones.size() > 4) { return false; } Set seenColors = new HashSet(); for (Stone i : stones) { if (i.isJoker()) { continue; } if (seenColors.contains(i.getColor())) { return false; } else { seenColors.add(i.getColor()); } } return true; } /** * Splits the StoneSet at a specified {@link Position} and returns two new * Stone Sets * * @param position * Splitting {@link Position} */ public Pair splitAt(int position) { // Exception in case of wrong index if (position == 0 || position == stones.size()) { throw new IndexOutOfBoundsException(); } StoneSet firstSet = new StoneSet(stones.subList(0, position)); StoneSet secondSet = new StoneSet(stones.subList(position, stones.size())); return new Pair(firstSet, secondSet); } /** * Joins StoneSet to another StoneSet and returns the resulting new StoneSet * * @param other * StoneSet to be joined to active StoneSet */ public StoneSet join(StoneSet other) { List joinedList = new ArrayList(); joinedList.addAll(stones); joinedList.addAll(other.stones); return new StoneSet(joinedList); } public int size() { return stones.size(); } public Stone get(int i) { return stones.get(i); } @Override public Iterator iterator() { final Iterator it = stones.iterator(); return new Iterator() { @Override public boolean hasNext() { return it.hasNext(); } @Override public Stone next() { return it.next(); } @Override public void remove() { // removing stones is impossible throw new NotImplementedException(); } }; } @Override public float getWidth() { return stones.size() + 2 * border; } @Override public float getHeight() { return 1; } }