Skip to content

Content of file TicTacToeStateImplTest.java

package de.fhdw.gaming.ipspiel23.tictactoe.core.domain.impl;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.junit.jupiter.api.Test;

import de.fhdw.gaming.core.domain.PlayerState;
import de.fhdw.gaming.ipspiel23.tictactoe.core.domain.TicTacToeFieldState;
import de.fhdw.gaming.ipspiel23.tictactoe.core.domain.TicTacToePlayer;
import de.fhdw.gaming.ipspiel23.tictactoe.core.domain.TicTacToePosition;

/**
 * Tests {@link TicTacToeStateImpl}.
 */
class TicTacToeStateImplTest {

    /**
     * Tests {@link TicTacToeStateImpl#equals(Object)}.
     */
    @Test
    void testEqualsObject() throws Exception {
        final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3);

        assertThrows( IllegalArgumentException.class, () -> new TicTacToeStateImpl(
'(' is followed by whitespace.

Since Checkstyle 3.0

Checks the policy on the padding of parentheses; i.e. whether a space is required after a left parenthesis and before a right parenthesis, or such spaces are forbidden. No check occurs at the right parenthesis after an empty for iterator, at the left parenthesis before an empty for initialization, or at the right parenthesis of a try-with-resources resource specification where the last resource variable has a trailing semi-colon. Use Check EmptyForIteratorPad to validate empty for iterators and EmptyForInitializerPad to validate empty for initializers. Typecasts are also not checked, as there is TypecastParenPad to validate them.

board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(false).build(), true)); assertThrows( IllegalArgumentException.class, () -> new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(true).build(), true)); assertThrows( IllegalArgumentException.class, () -> new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(false).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true)); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat( state, is( equalTo( new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true) .build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false) .build(), true)))); assertThat( state, is( not( equalTo( new TicTacToeStateImpl( new TicTacToeBoardImpl(4), new TicTacToePlayerBuilderImpl().changeName("A") .changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B") .changeUsingCrosses(false).build(), true))))); assertThat( state, is( not( equalTo( new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("X") .changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B") .changeUsingCrosses(false).build(), true))))); assertThat( state, is( not( equalTo( new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A") .changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("Y") .changeUsingCrosses(false).build(), true))))); assertThat( state, is( not( equalTo( new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("B") .changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("A") .changeUsingCrosses(false).build(), true))))); assertThat( state, is( not( equalTo( new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A") .changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B") .changeUsingCrosses(false).build(), false))))); // null assertNotEquals(null, state); // different class assertNotEquals("not a state", state); assertNotEquals(0, state.hashCode()); } /** * Tests {@link TicTacToeStateImpl#deepCopy()}. */ @Test void testDeepCopy() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); board.getFieldAt(TicTacToePosition.of(0, 0)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(1, 0)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(0, 1)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(1, 1)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(2, 0)).changeState(TicTacToeFieldState.CROSS); assertThat( state.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).getState(), is(equalTo(TicTacToeFieldState.EMPTY))); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); final TicTacToeStateImpl stateCopy = state.deepCopy(); assertThat( stateCopy.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).getState(), is(equalTo(TicTacToeFieldState.EMPTY))); assertThat(stateCopy.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(stateCopy.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); // change of origin does not change the copy state.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).changeState(TicTacToeFieldState.NOUGHT); state.moveCompleted(); assertThat( state.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).getState(), is(equalTo(TicTacToeFieldState.NOUGHT))); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.LOST))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.WON))); assertThat( stateCopy.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).getState(), is(equalTo(TicTacToeFieldState.EMPTY))); assertThat(stateCopy.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(stateCopy.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); // transfer change manually from origin to copy stateCopy.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).changeState(TicTacToeFieldState.NOUGHT); stateCopy.moveCompleted(); assertThat( stateCopy.getBoard().getFieldAt(TicTacToePosition.of(1, 2)).getState(), is(equalTo(TicTacToeFieldState.NOUGHT))); assertThat(stateCopy.getPlayers().get("A").getState(), is(equalTo(PlayerState.LOST))); assertThat(stateCopy.getPlayers().get("B").getState(), is(equalTo(PlayerState.WON))); // change of copy does not change the origin stateCopy.getBoard().getFieldAt(TicTacToePosition.of(2, 2)).changeState(TicTacToeFieldState.CROSS); assertThat( stateCopy.getBoard().getFieldAt(TicTacToePosition.of(2, 2)).getState(), is(equalTo(TicTacToeFieldState.CROSS))); assertThat( state.getBoard().getFieldAt(TicTacToePosition.of(2, 2)).getState(), is(equalTo(TicTacToeFieldState.EMPTY))); } /** * Tests {@link TicTacToeStateImpl#getPlayers()}. */ @Test void testGetPlayers() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); final Map<String, TicTacToePlayer> players = state.getPlayers(); assertThat(players.entrySet(), hasSize(2)); assertThat(players.keySet(), containsInAnyOrder("A", "B")); assertThat(players.get("A"), is(equalTo(new TicTacToePlayerImpl("A", true)))); assertThat(players.get("B"), is(equalTo(new TicTacToePlayerImpl("B", false)))); } /** * Tests {@link TicTacToeStateImpl#getPlayerState(String)} and * {@link TicTacToeStateImpl#setPlayerState(String, de.fhdw.gaming.core.domain.PlayerState)}. */ @Test void testGetAndSetPlayerState() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); state.getPlayers().get("A").setState(PlayerState.WON); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.WON))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); state.getPlayers().get("B").setState(PlayerState.LOST); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.WON))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.LOST))); } /** * Tests {@link TicTacToeStateImpl#getPlayerOutcome(String)} and * {@link TicTacToeStateImpl#setPlayerOutcome(String, double)}. */ @Test void testGetAndSetPlayerOutcome() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getPlayers().get("A").getOutcome(), is(equalTo(Optional.empty()))); assertThat(state.getPlayers().get("B").getOutcome(), is(equalTo(Optional.empty()))); // players are still playing assertThrows(IllegalStateException.class, () -> state.getPlayers().get("A").setOutcome(2.0)); assertThrows(IllegalStateException.class, () -> state.getPlayers().get("B").setOutcome(-2.0)); state.getPlayers().get("A").setState(PlayerState.WON); state.getPlayers().get("B").setState(PlayerState.LOST); assertThat(state.getPlayers().get("A").getOutcome(), is(equalTo(Optional.of(1.0)))); assertThat(state.getPlayers().get("B").getOutcome(), is(equalTo(Optional.of(-1.0)))); state.getPlayers().get("A").setOutcome(3.5); assertThat(state.getPlayers().get("A").getOutcome(), is(equalTo(Optional.of(3.5)))); assertThat(state.getPlayers().get("B").getOutcome(), is(equalTo(Optional.of(-1.0)))); state.getPlayers().get("B").setOutcome(-2.5); assertThat(state.getPlayers().get("A").getOutcome(), is(equalTo(Optional.of(3.5)))); assertThat(state.getPlayers().get("B").getOutcome(), is(equalTo(Optional.of(-2.5)))); state.getPlayers().get("A").setState(PlayerState.PLAYING); state.getPlayers().get("B").setState(PlayerState.PLAYING); assertThat(state.getPlayers().get("A").getOutcome(), is(equalTo(Optional.empty()))); assertThat(state.getPlayers().get("B").getOutcome(), is(equalTo(Optional.empty()))); } /** * Tests {@link TicTacToeStateImpl#getBoard()}. */ @Test void testGetBoard() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getBoard(), is(equalTo(board))); } /** * Tests {@link TicTacToeStateImpl#getCrossesPlayer()}. */ @Test void testGetCrossesPlayer() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getCrossesPlayer(), is(equalTo(state.getPlayers().get("A")))); } /** * Tests {@link TicTacToeStateImpl#getNoughtsPlayer()}. */ @Test void testGetNoughtsPlayer() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getNoughtsPlayer(), is(equalTo(state.getPlayers().get("B")))); } /** * Tests {@link TicTacToeStateImpl#getCurrentPlayer()}. */ @Test void testGetCurrentPlayer() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getCurrentPlayer(), is(equalTo(state.getPlayers().get("A")))); } /** * Tests {@link TicTacToeStateImpl#moveCompleted()} where one player wins (and the other player loses) the game. */ @Test void testMoveCompletedWonLost() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); board.getFieldAt(TicTacToePosition.of(0, 0)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(1, 0)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(0, 1)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(2, 0)).changeState(TicTacToeFieldState.NOUGHT); state.moveCompleted(); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); board.getFieldAt(TicTacToePosition.of(0, 2)).changeState(TicTacToeFieldState.CROSS); state.moveCompleted(); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.WON))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.LOST))); } /** * Tests {@link TicTacToeStateImpl#moveCompleted()} where one player loses (and the other player wins) the game. */ @Test void testMoveCompletedLostWon() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); board.getFieldAt(TicTacToePosition.of(0, 0)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(1, 0)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(0, 1)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(1, 1)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(2, 0)).changeState(TicTacToeFieldState.CROSS); state.moveCompleted(); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); board.getFieldAt(TicTacToePosition.of(1, 2)).changeState(TicTacToeFieldState.NOUGHT); state.moveCompleted(); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.LOST))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.WON))); } /** * Tests {@link TicTacToeStateImpl#moveCompleted()} where the game ends in a draw. */ @Test void testMoveCompletedDraw() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); board.getFieldAt(TicTacToePosition.of(1, 1)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(0, 0)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(2, 0)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(0, 2)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(0, 1)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(1, 2)).changeState(TicTacToeFieldState.NOUGHT); board.getFieldAt(TicTacToePosition.of(2, 2)).changeState(TicTacToeFieldState.CROSS); board.getFieldAt(TicTacToePosition.of(2, 1)).changeState(TicTacToeFieldState.NOUGHT); state.moveCompleted(); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.PLAYING))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.PLAYING))); board.getFieldAt(TicTacToePosition.of(1, 0)).changeState(TicTacToeFieldState.CROSS); state.moveCompleted(); assertThat(state.getPlayers().get("A").getState(), is(equalTo(PlayerState.DRAW))); assertThat(state.getPlayers().get("B").getState(), is(equalTo(PlayerState.DRAW))); } /** * Tests {@link TicTacToeStateImpl#computeNextPlayers()}. */ @Test void testComputeNextPlayers() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.computeNextPlayers(), is(equalTo(Set.of(state.getPlayers().get("A"))))); } /** * Tests {@link TicTacToeStateImpl#nextTurn()}. */ @Test void testNextTurn() throws Exception { final TicTacToeBoardImpl board = new TicTacToeBoardImpl(3); final TicTacToeStateImpl state = new TicTacToeStateImpl( board, new TicTacToePlayerBuilderImpl().changeName("A").changeUsingCrosses(true).build(), new TicTacToePlayerBuilderImpl().changeName("B").changeUsingCrosses(false).build(), true); assertThat(state.getCurrentPlayer(), is(equalTo(state.getPlayers().get("A")))); assertThat(state.computeNextPlayers(), is(equalTo(Set.of(state.getPlayers().get("A"))))); state.nextTurn(); assertThat(state.getCurrentPlayer(), is(equalTo(state.getPlayers().get("B")))); assertThat(state.computeNextPlayers(), is(equalTo(Set.of(state.getPlayers().get("B"))))); state.nextTurn(); assertThat(state.getCurrentPlayer(), is(equalTo(state.getPlayers().get("A")))); assertThat(state.computeNextPlayers(), is(equalTo(Set.of(state.getPlayers().get("A"))))); } }