add more ways to construct a combination

main
jbb01 2 years ago
parent 0d1f51d868
commit 681942e02d

@ -1,18 +1,23 @@
package eu.jonahbauer.tichu.common.model;
import eu.jonahbauer.tichu.common.model.combinations.*;
import eu.jonahbauer.tichu.common.model.exceptions.InvalidCombinationException;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.Function;
/**
* A type of combination.
*/
@RequiredArgsConstructor
public enum CombinationType {
/**
* A single card, {@linkplain Card#isNormal() normal} or {@linkplain Card#isSpecial() special}. This is the
* correct {@code CombinationType} for playing the {@link Card#HOUND} or {@link Card#DRAGON}.
*/
SINGLE {
SINGLE(Single.class, Single::of) {
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX, Card.MAHJONG, Card.DRAGON, Card.HOUND);
@Override
@ -24,7 +29,7 @@ public enum CombinationType {
* A pair, i.e. two {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value} or the
* {@link Card#PHOENIX} and a normal card.
*/
PAIR {
PAIR(Pair.class, Pair::of) {
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
private static final int[] INDICES = new int[] {0, 1};
@ -38,7 +43,7 @@ public enum CombinationType {
* A triple, i.e. three {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value}
* or the {@linkplain Card#PHOENIX} and two normal cards of the same value.
*/
TRIPLE {
TRIPLE(Triple.class, Triple::of) {
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
private static final int[] INDICES = new int[] {0, 1, 2};
@ -53,7 +58,7 @@ public enum CombinationType {
* @apiNote A list of cards representing a full house must have the triple at the first three indices and the pair
* at the last two. This prevents any ambiguity, e.g. when the full house consists of two pairs and the phoenix.
*/
FULL_HOUSE {
FULL_HOUSE(FullHouse.class, FullHouse::of) {
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
private static final int[] INDICES_TRIPLE = new int[] {0, 1, 2};
@ -72,7 +77,7 @@ public enum CombinationType {
* @apiNote A list of cards representing a sequence must be sorted by ascending value. This allows to distinguish
* between a sequence starting with the phoenix and a sequence ending with the phoenix.
*/
SEQUENCE {
SEQUENCE(SingleSequence.class, SingleSequence::of) {
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX, Card.MAHJONG);
private int getStartValue(@NotNull List<@NotNull Card> cards) {
@ -107,7 +112,7 @@ public enum CombinationType {
* @apiNote Although not strictly necessary, for consistency with {@link #SEQUENCE} a list of cards representing
* a sequence of pairs must be sorted by ascending value.
*/
PAIR_SEQUENCE {
PAIR_SEQUENCE(PairSequence.class, PairSequence::of) {
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
private int getStartValue(@NotNull List<@NotNull Card> cards) {
@ -137,7 +142,7 @@ public enum CombinationType {
/**
* A bomb, i.e. four {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value}.
*/
BOMB {
BOMB(BombTuple.class, BombTuple::of) {
private static final int[] INDICES = new int[] {0, 1, 2, 3};
private static final Set<Card> SPECIAL_CARDS = Collections.emptySet();
@ -154,7 +159,7 @@ public enum CombinationType {
* bomb sequence must be sorted by ascending value.
* @apiNote
*/
BOMB_SEQUENCE {
BOMB_SEQUENCE(BombSequence.class, BombSequence::of) {
private static final Set<Card> SPECIAL_CARDS = Collections.emptySet();
private int getStartValue(@NotNull List<@NotNull Card> cards) {
@ -179,14 +184,48 @@ public enum CombinationType {
}
};
private final @NotNull Class<? extends Combination> combinationClass;
private final @NotNull Function<@NotNull List<@NotNull Card>, @NotNull Combination> factory;
/**
* Checks whether the given cards form a valid combination of this type. See the documentation of a specific
* {@code CombinationType} for more information on what cards form a combination of that particular type.
* @param cards a list of cards
* @return {@code true} if the cards form a valid combination of this type.
* @throws NullPointerException if the list or any of its elements are {@code null}.
*/
public abstract boolean check(@NotNull List<@NotNull Card> cards);
/**
* Creates a new combination of this type consisting of the given cards.
* @param cards a list of cards forming a {@linkplain #check(List) valid} combination
* @return a new combination.
* @throws InvalidCombinationException if the given cards do not form a valid combination.
* @throws NullPointerException if the list or any of its elements are {@code null}.
*/
public @NotNull Combination of(@NotNull List<@NotNull Card> cards) {
return factory.apply(cards);
}
/**
* Creates a new combination of this type consisting of the given cards.
* @param cards a list of cards forming a {@linkplain #check(List) valid} combination
* @return a new combination.
* @throws InvalidCombinationException if the given cards do not form a valid combination.
* @throws NullPointerException if the list or any of its elements are {@code null}.
*/
public @NotNull Combination of(@NotNull Card @NotNull... cards) {
return of(List.of(cards));
}
/**
* Returns the class representing a combination of this type.
* @return the class representing a combination of this type.
*/
public @NotNull Class<? extends Combination> getCombinationClass() {
return combinationClass;
}
//<editor-fold desc="Utility Methods" defaultstate="collapsed">
/**
* Performs basic checks on a list of cards, i.e. this method checks

@ -3,6 +3,7 @@ package eu.jonahbauer.tichu.common.model.combinations;
import eu.jonahbauer.tichu.common.model.Card;
import eu.jonahbauer.tichu.common.model.CombinationType;
import eu.jonahbauer.tichu.common.model.Stack;
import eu.jonahbauer.tichu.common.model.exceptions.InvalidCombinationException;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range;
@ -79,9 +80,11 @@ public sealed interface Combination extends Serializable permits AbstractCombina
/**
* Creates a new combination of the given type consisting of the given cards.
* @param type a combination type
* @param cards a list of cards forming a {@linkplain CombinationType#check(List) valid} combination
* @return a new combination
* @param type a combination type
* @return a new combination.
* @throws InvalidCombinationException if the given cards do not form a valid combination.
* @throws NullPointerException if the type, the list or any of its elements are {@code null}.
*/
@Contract("_, _ -> new")
static Combination of(@NotNull CombinationType type, @NotNull List<@NotNull Card> cards) {

Loading…
Cancel
Save