Skip to content

Content of file VGStateImpl.java

package de.fhdw.gaming.ipspiel22.vierGewinnt.domain.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import de.fhdw.gaming.core.domain.GameException;
import de.fhdw.gaming.core.domain.PlayerState;
import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGBoard;
import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGField;
import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGFieldState;
import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGPlayer;
import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGState;

/**
 * Implements {@link VGState}.
 */
public class VGStateImpl implements VGState {

    /**
     * The board.
     */
    private final VGBoard board;
    /**
     * The first player.
     */
    private final VGPlayer redPlayer;
    /**
     * The second player.
     */
    private final VGPlayer yellowPlayer;
    /**
     * The current player.
     */
    private VGPlayer currentPlayer;

    /**
     * Creates a Vier gewinnt state.
     *
     * @param board        A board.s
     * @param redPlayer    The first player.
     * @param yellowPlayer The second player.
     * @param redIsNext    Is red next.
     * @throws GameException if the state cannot be created according to the rules of the game.
     */
    public VGStateImpl(final VGBoard board, final VGPlayer redPlayer, final VGPlayer yellowPlayer,
            final boolean redIsNext)
            throws GameException {

        this.board = Objects.requireNonNull(board, "board");
        this.redPlayer = Objects.requireNonNull(redPlayer, "redPlayerBuilder");
        this.yellowPlayer = Objects.requireNonNull(yellowPlayer, "yellowPlayerBuilder");
        this.currentPlayer = redIsNext ? this.redPlayer : this.yellowPlayer;

        if (!this.redPlayer.isUsingRedChips()) {
            throw new IllegalArgumentException(
                    String.format("Red player %s does not use red chips.", this.redPlayer));
        }
        if (this.yellowPlayer.isUsingRedChips()) {
            throw new IllegalArgumentException(
                    String.format("Yellow player %s does not use yellow tokens.", this.yellowPlayer));
        }
        if (this.redPlayer.getName().equals(this.yellowPlayer.getName())) {
            throw new IllegalArgumentException(
                    String.format("Both players have the same name '%s'.", this.redPlayer.getName()));
        }
    }

    /**
     * Creates a Vier gewinnt state by copying an existing one.
     *
     * @param source The state to copy.
     */
    VGStateImpl(final VGStateImpl source) {
        this.board = source.board.deepCopy();
        this.redPlayer = source.redPlayer.deepCopy();
        this.yellowPlayer = source.yellowPlayer.deepCopy();
        this.currentPlayer = source.isRedPlayerCurrent() ? this.redPlayer : this.yellowPlayer;
    }

    @Override
    public String toString() {
        return String.format(
                "VGState[board=%s, redPlayer=%s, yellowPlayer=%s, currentPlayer=%s]",
                this.board,
                this.redPlayer,
                this.yellowPlayer,
                this.currentPlayer.isUsingRedChips() ? VGFieldState.RED : VGFieldState.YELLOW);
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj instanceof VGStateImpl) {
            final VGStateImpl other = (VGStateImpl) obj;
            return this.board.equals(other.board)
                    && this.redPlayer.equals(other.redPlayer)
                    && this.yellowPlayer.equals(other.yellowPlayer)
                    && this.isRedPlayerCurrent() == other.isRedPlayerCurrent();
        }
        return false;
    }

    @Override
    public VGState deepCopy() {
        return new VGStateImpl(this);
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.board, this.redPlayer, this.yellowPlayer, this.isRedPlayerCurrent());
    }

    @Override
    public Map<String, VGPlayer> getPlayers() {
        final Map<String, VGPlayer> result = new LinkedHashMap<>();
        result.put(this.redPlayer.getName(), this.redPlayer);
        result.put(this.yellowPlayer.getName(), this.yellowPlayer);
        return result;
    }

    @Override
    public Set<VGPlayer> computeNextPlayers() {
        return Collections.singleton(this.currentPlayer);
    }

    @Override
    public void nextTurn() {
        final List<VGField> allFields = new ArrayList<>();
        this.getBoard().getFields().forEach(allFields::addAll);

        if (allFields.stream().noneMatch(vgField -> vgField.getState().equals(VGFieldState.EMPTY))) {

            System.out.println("Board ist voll");

            if (this.checkWinner(this.currentPlayer)) {
                this.currentPlayer.setState(PlayerState.WON);
                System.out.println(this.currentPlayer.getName() + " hat gewonnen, mit der Farbe: "
                        + (this.currentPlayer.isUsingRedChips()
                                ? VGFieldState.RED.toString()
                                : VGFieldState.YELLOW.toString()));
                this.getOtherPlayer().setState(PlayerState.LOST);
                System.out.println(this.getOtherPlayer().getName() + " hat verloren, mit der Farbe: "
                        + (this.currentPlayer.isUsingRedChips()
                                ? VGFieldState.YELLOW.toString()
                                : VGFieldState.RED.toString()));
            } else {
                this.gameOver();
            }
        } else if (this.checkWinner(this.currentPlayer)) {
            this.currentPlayer.setState(PlayerState.WON);
            System.out.println(this.currentPlayer.getName() + " hat gewonnen, mit der Farbe: "
                    + (this.currentPlayer.isUsingRedChips()
                            ? VGFieldState.RED.toString()
                            : VGFieldState.YELLOW.toString()));
            this.getOtherPlayer().setState(PlayerState.LOST);
            System.out.println(this.getOtherPlayer().getName() + " hat verloren, mit der Farbe: "
                    + (this.currentPlayer.isUsingRedChips()
                            ? VGFieldState.YELLOW.toString()
                            : VGFieldState.RED.toString()));
        }
        this.currentPlayer = this.getOtherPlayer();
    }

    /**
     * Returns boolean, if Player has won.
     *
     * @param player The current player.
     */
    public boolean checkWinner(final VGPlayer player) {
        VGFieldState state = VGFieldState.YELLOW;
        if (player.isUsingRedChips()) {
            state = VGFieldState.RED;
        }
        return this.checkVertical(state);
    }

    /**
     * Returns boolean, if Player has won.
     *
     * @param state The chips color of the current player.
     */
    private Boolean checkVertical(final VGFieldState state) {
        for (int i = 0; i < this.board.getColumns(); i++) {
            for (int j = 0; j < 3; j++) {
                if (this.board.getFields().get(i).get(j).getState().equals(state)
                        && this.board.getFields().get(i).get(j + 1).getState().equals(state)
                        && this.board.getFields().get(i).get(j + 2).getState().equals(state)
                        && this.board.getFields().get(i).get(j + 3).getState().equals(state)) {
                    System.out.println(
                            "Vertikal: " + this.board.getFields().get(i).get(j).getPosition()
                                    + this.board.getFields().get(i).get(j + 1).getPosition()
                                    + this.board.getFields().get(i).get(j + 2).getPosition()
                                    + this.board.getFields().get(i).get(j + 3).getPosition());
                    return true;
                }
            }
        }
        return this.checkHorizontal(state);
    }

    /**
     * Returns boolean, if Player has won.
     *
     * @param state The chips color of the current player.
     */
    private Boolean checkHorizontal(final VGFieldState state) {
        for (int i = 0; i < this.board.getRows(); i++) { // Für Zeilen
            for (int j = 0; j < 4; j++) { // Für Spalten
                if (this.board.getFields().get(j).get(i).getState().equals(state)
                        && this.board.getFields().get(j + 1).get(i).getState().equals(state)
                        && this.board.getFields().get(j + 2).get(i).getState().equals(state)
                        && this.board.getFields().get(j + 3).get(i).getState().equals(state)) {
                    System.out.println(
                            "Horizontal: " + this.board.getFields().get(j).get(i).getPosition()
                                    + this.board.getFields().get(j + 1).get(i).getPosition()
                                    + this.board.getFields().get(j + 2).get(i).getPosition()
                                    + this.board.getFields().get(j + 3).get(i).getPosition());
                    return true;
                }
            }
        }
        return this.checkDiagonalLeftToRight(state);
    }

    /**
     * Returns boolean, if Player has won.
     *
     * @param state The chips color of the current player.
     */
    private Boolean checkDiagonalLeftToRight(final VGFieldState state) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                if (this.board.getFields().get(j).get(i).getState().equals(state)
                        && this.board.getFields().get(j + 1).get(i + 1).getState().equals(state)
                        && this.board.getFields().get(j + 2).get(i + 2).getState().equals(state)
                        && this.board.getFields().get(j + 3).get(i + 3).getState().equals(state)) {
                    System.out.println("Diagonal von links nach rechts: "
                            + this.board.getFields().get(j).get(i).getPosition()
                            + this.board.getFields().get(j + 1).get(i + 1).getPosition()
                            + this.board.getFields().get(j + 2).get(i + 2).getPosition()
                            + this.board.getFields().get(j + 3).get(i + 3).getPosition());
                    return true;
                }
            }
        }
        return this.checkDiagonalRightToLeft(state);
    }

    /**
     * Returns boolean, if Player has won.
     *
     * @param state The chips color of the current player.
     */
    private Boolean checkDiagonalRightToLeft(final VGFieldState state) {
        for (int i = 0; i < 3; i++) {
            for (int j = 3; j < 7; j++) {
                if (this.board.getFields().get(j).get(i).getState().equals(state)
                        && this.board.getFields().get(j - 1).get(i + 1).getState().equals(state)
                        && this.board.getFields().get(j - 2).get(i + 2).getState().equals(state)
                        && this.board.getFields().get(j - 3).get(i + 3).getState().equals(state)) {
                    System.out.println("Diagonal von links nach rechts: "
                            + this.board.getFields().get(j).get(i).getPosition()
                            + this.board.getFields().get(j - 1).get(i + 1).getPosition()
                            + this.board.getFields().get(j - 2).get(i + 2).getPosition()
                            + this.board.getFields().get(j - 3).get(i + 3).getPosition());
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public VGBoard getBoard() {
        return this.board;
    }

    @Override
    public VGPlayer getRedPlayer() {
        return this.redPlayer;
    }

    @Override
    public VGPlayer getYellowPlayer() {
        return this.yellowPlayer;
    }

    @Override
    public VGPlayer getCurrentPlayer() {
        return this.currentPlayer;
    }

    /**
     * Returns the currently inactive player.
     */
    private VGPlayer getOtherPlayer() {
        if (this.isRedPlayerCurrent()) {
            return this.yellowPlayer;
        }
        return this.redPlayer;
    }

    /**
     * Returns id the current player is the red Player.
     */
    private boolean isRedPlayerCurrent() {
        return this.currentPlayer.equals(this.redPlayer);
    }

    @Override
    public void gameOver() {
        this.redPlayer.setState(PlayerState.DRAW);
        this.yellowPlayer.setState(PlayerState.DRAW);
        System.out.println("Es ist untenschieden. ");
    }
}
Possible God Class (WMC=64, ATFD=18, TCC=9.357%).
The God Class rule detects the God Class design flaw using metrics. God classes do too many things, are very big and overly complex. They should be split apart to be more object-oriented. The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". The violations are reported against the entire class. The rule uses metrics to implement its detection strategy. The violation message gives information about the values of these metrics: * WMC: a class complexity measure, see {% jdoc java::lang.java.metrics.JavaMetrics#WEIGHED_METHOD_COUNT %} * ATFD: a measure of how much data external data the class uses, see {% jdoc java::lang.java.metrics.JavaMetrics#ACCESS_TO_FOREIGN_DATA %} * TCC: a measure of how tightly related the methods are, see {% jdoc java::lang.java.metrics.JavaMetrics#TIGHT_CLASS_COHESION %} The rule identifies a god class by looking for classes which have all of the following properties: * High WMC * High ATFD * Low TCC See also the reference: Michele Lanza and Radu Marinescu. *Object-Oriented Metrics in Practice: Using Software Metrics to Characterize, Evaluate, and Improve the Design of Object-Oriented Systems.* Springer, Berlin, 1 edition, October 2006. Page 80. See PMD documentation.