Skip to main content
replaced http://meta.codereview.stackexchange.com/ with https://codereview.meta.stackexchange.com/
Source Link

As many may know, I am developing a Trading Card Game for the Coding ChallengeCoding Challenge.

As many may know, I am developing a Trading Card Game for the Coding Challenge.

As many may know, I am developing a Trading Card Game for the Coding Challenge.

added 11 characters in body; edited tags
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

As many may know, I am developing a Trading Card Game for the Coding Challenge.
I

I have just completed the Field class and have not used it in practice yet, so all theoretical and looking for a review.
Using

Using Java 8 and all custom classes will be included in this post aswellas well, if you wish you can see all source on https://github.com/skiwi2/TCGGitHub.

As many may know, I am developing a Trading Card Game for the Coding Challenge.
I have just completed the Field class and have not used it in practice yet, so all theoretical and looking for a review.
Using Java 8 and all custom classes will be included in this post aswell, if you wish you can see all source on https://github.com/skiwi2/TCG.

As many may know, I am developing a Trading Card Game for the Coding Challenge.

I have just completed the Field class and have not used it in practice yet, so all theoretical and looking for a review.

Using Java 8 and all custom classes will be included in this post as well, if you wish you can see all source on GitHub.

Source Link
skiwi
  • 10.6k
  • 6
  • 44
  • 108

Field class used by my trading card game

As many may know, I am developing a Trading Card Game for the Coding Challenge.
I have just completed the Field class and have not used it in practice yet, so all theoretical and looking for a review.
Using Java 8 and all custom classes will be included in this post aswell, if you wish you can see all source on https://github.com/skiwi2/TCG.

The field currently only consists of monsters that can be on the field, though in the future other types of cards may be added.

The Field class:

public class Field {
    private final MonsterCard[] monsters;

    public Field(final int monsterCapacity) {
        Arguments.requirePositive(monsterCapacity, "monster capacity");
        this.monsters = new MonsterCard[monsterCapacity];
    }

    public void setMonster(final int index, final MonsterCard monsterCard) {
        Arguments.requireIndexInRange(index, 0, monsters.length);
        Objects.requireNonNull(monsterCard);
        monsters[index] = monsterCard;
    }

    public MonsterCard getMonster(final int index) {
        Arguments.requireIndexInRange(index, 0, monsters.length);
        MonsterCard monsterCard = monsters[index];
        States.requireNonNull(monsterCard, NoSuchElementException::new, "no monster exists on index: " + index);
        return monsterCard;
    }

    public boolean hasMonster(final int index) {
        Arguments.requireIndexInRange(index, 0, monsters.length);
        return (monsters[index] != null);
    }

    public MonsterCard destroyMonster(final int index) {
        Arguments.requireIndexInRange(index, 0, monsters.length);
        MonsterCard monsterCard = monsters[index];
        States.requireNonNull(monsterCard, NoSuchElementException::new, "no monster exists on index: " + index);
        monsters[index] = null;
        return monsterCard;
    }

    public Stream<MonsterCard> getMonsters() {
        return Arrays.stream(monsters).filter(obj -> obj != null);
    }

    public int getMonsterCapacity() {
        return monsters.length;
    }

    @Override
    public String toString() {
        return "Field(" + Arrays.toString(monsters) + ")";
    }
}

The unit tests:

public class FieldTest {
    static {
        assertTrue(true);
    }

    @Test
    public void testConstructor() {
        new Field(1);
        new Field(6);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructorZeroMonsterCapacity() {
        new Field(0);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructorNegativeMonsterCapacity() {
        new Field(-1);
    }

    @Test
    public void testSetMonster() {
        Field field = new Field(6);
        MonsterCard monsterCard = createMonsterCard();
        field.setMonster(0, monsterCard);
        assertEquals(monsterCard, field.getMonster(0));

        MonsterCard monsterCard2 = createMonsterCard2();
        field.setMonster(5, monsterCard2);
        assertEquals(monsterCard2, field.getMonster(5));
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testSetMonsterUnderRange() {
        Field field = new Field(6);
        field.setMonster(-1, createMonsterCard());
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testSetMonsterAboveRange() {
        Field field = new Field(6);
        field.setMonster(6, createMonsterCard());
    }

    @Test(expected = NullPointerException.class)
    public void testSetMonsterMonsterCardNull() {
        Field field = new Field(6);
        field.setMonster(0, null);
    }

    @Test
    public void testGetMonster() {
        Field field = new Field(6);
        MonsterCard monsterCard = createMonsterCard();
        field.setMonster(0, monsterCard);
        assertEquals(monsterCard, field.getMonster(0));
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testGetMonsterUnderRange() {
        Field field = new Field(6);
        field.getMonster(-1);
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testGetMonsterAboveRange() {
        Field field = new Field(6);
        field.getMonster(6);
    }

    @Test(expected = NoSuchElementException.class)
    public void testGetMonsterNoMonster() {
        Field field = new Field(6);
        field.getMonster(0);
    }

    @Test
    public void testHasMonster() {
        Field field = new Field(6);
        field.setMonster(0, createMonsterCard());
        assertTrue(field.hasMonster(0));
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testHasMonsterUnderRange() {
        Field field = new Field(6);
        field.hasMonster(-1);
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testHasMonsterAboveRange() {
        Field field = new Field(6);
        field.hasMonster(6);
    }

    @Test
    public void testDestroyMonster() {
        Field field = new Field(6);
        MonsterCard monsterCard = createMonsterCard();
        field.setMonster(0, monsterCard);
        assertEquals(monsterCard, field.destroyMonster(0));
        assertFalse(field.hasMonster(0));
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testDestroyMonsterUnderRange() {
        Field field = new Field(6);
        field.destroyMonster(-1);
    }

    @Test(expected = IndexOutOfBoundsException.class)
    public void testDestroyMonsterAboveRange() {
        Field field = new Field(6);
        field.destroyMonster(6);
    }

    @Test(expected = NoSuchElementException.class)
    public void testDestroyMonsterNoMonster() {
        Field field = new Field(6);
        field.destroyMonster(0);
    }

    @Test
    public void testGetMonsters() {
        Field field = new Field(6);
        assertEquals(0, field.getMonsters().count());
        assertFalse(field.getMonsters().anyMatch(m -> m == null));

        MonsterCard monsterCard = createMonsterCard();
        MonsterCard monsterCard2 = createMonsterCard2();
        field.setMonster(0, monsterCard);
        field.setMonster(1, monsterCard2);
        List<MonsterCard> list = field.getMonsters().collect(Collectors.toList());
        assertTrue(list.contains(monsterCard));
        assertTrue(list.contains(monsterCard2));
    }

    @Test
    public void testGetMonsterCapacity() {
        Field field = new Field(6);
        assertEquals(6, field.getMonsterCapacity());
    }

    @Test
    public void testToString() {
        Field field = new Field(5);
        MonsterCard monsterCard = createMonsterCard();
        MonsterCard monsterCard2 = createMonsterCard2();
        field.setMonster(1, monsterCard);
        field.setMonster(3, monsterCard2);
        assertEquals("Field([null, " + monsterCard.toString() + ", null, " + monsterCard2.toString() + ", null])", field.toString());
    }

    private MonsterCard createMonsterCard() {
        return new MonsterCard("Test", 5, 5, MonsterModus.HEALING);
    }

    private MonsterCard createMonsterCard2() {
        return new MonsterCard("zzz", 7, 7, MonsterModus.OFFENSIVE);
    }
}

The relevant Arguments and States snippets:

public static int requirePositive(final int value, final String name) throws IllegalArgumentException {
    Objects.requireNonNull(name);
    if (value <= 0) {
        throw new IllegalArgumentException("the " + name + " must be positive: " + value);
    }
    return value;
}

public static int requireIndexInRange(final int index, final int lowInclusive, final int highExclusive) throws IndexOutOfBoundsException {
    if (index < lowInclusive || index >= highExclusive) {
        throw new IndexOutOfBoundsException("the index must be in range: " + index + ", expected: [" + lowInclusive + ", " + highExclusive + ")");
    }
    return index;
}

public static <T, E extends RuntimeException> T requireNonNull(final T object, final Function<String, E> exceptionFunction, final String message) throws E {
    Objects.requireNonNull(exceptionFunction);
    Objects.requireNonNull(message);
    if (object == null) {
        throw exceptionFunction.apply(message);
    }
    return object;
}

A few notes:

  • In the unit tests I explicitely create a new Field(6) every time, as the arguments are important to know.
  • The static { assertTrue(true); } is there such that Netbeans stop annoying me, it is standard in all my unit tests.
  • I use an experimental approach of providing a Stream<E> as view of a class as opposed to the Java 7-and-below standard of Collection<E>. The Java 8 developers encourage working with streams over the old collections API for writing API's.