Package model

Source Code of model.GameModel

package model;

import model.field.Field;
import model.field.IField;
import model.field.State;
import org.apache.log4j.Logger;
import util.ClassName;

public class GameModel {
    private static final Logger logger = Logger.getLogger(ClassName.getCurrentClassName());

    private static final int MINIMAL_FIELD_SIZE = 0;
    private static final int MAXIMUM_FIELD_SIZE = 20;
    private static final int MINIMAL_WIN_LINE_LENGTH = 0;

    private final int totalMovesCount;
    private final int winLineLength;

    private State turnState = State.CROSS;
    private int moveCounter = 0;
    private boolean isGameEnded = false;
    private State gameWinner = State.NONE;

    protected Field gameField;


    public GameModel(int fieldSize, int winLineLength) {
        logger.debug(String.format("field size %d, win line length %d", fieldSize, winLineLength));
        if (fieldSize <= MINIMAL_FIELD_SIZE || fieldSize > MAXIMUM_FIELD_SIZE ||
            winLineLength <= MINIMAL_WIN_LINE_LENGTH || winLineLength > fieldSize) {
            throw new IllegalArgumentException();
        }

        this.winLineLength = winLineLength;
        this.totalMovesCount = fieldSize * fieldSize;

        gameField = new Field(fieldSize);
    }

    public boolean doMove(int row, int column) {
        logger.debug(String.format("attempting to commit move [%d, %d] for field %s ", row, column, gameField.toString()));
        if (!gameField.isCellPositionCorrect(row, column) || !gameField.isCellEmpty(row, column)) {
            logger.warn(String.format("cell [%d, %d] is not free", row, column));
            return false;
        }
        moveCounter++;
        gameField.setCellState(row, column, turnState);
        logger.debug("move committed");
        checkGameState(row, column);
        nextGameTurnState();
        logger.debug("field state after committed move " + gameField.toString());
        return true;
    }

    private void nextGameTurnState() {
        logger.debug("switching turn from " + turnState);
        turnState = (turnState == State.CIRCLE) ? State.CROSS : State.CIRCLE;
    }

    private int getLineLength(int row,      int column,
                              int rowShift, int columnShift) {
        State lineState = gameField.getCellState(row, column);

        // exclude start point from length
        int counter = -1;
        do {
            row += rowShift;
            column += columnShift;
            counter++;
        } while (gameField.isCellPositionCorrect(row, column) &&
                (gameField.getCellState(row, column) == lineState));

        return counter;
    }

    private boolean isWinLineConstructed(int row, int column) {
        // calculating line length in different directions: south+north, west+east, etc.
        return (getLineLength(row, column, 10) + getLineLength(row, column, -10) >= winLineLength - 1) ||
               (getLineLength(row, column, 01) + getLineLength(row, column,  0, -1) >= winLineLength - 1) ||
               (getLineLength(row, column, 11) + getLineLength(row, column, -1, -1) >= winLineLength - 1) ||
               (getLineLength(row, column, 1, -1) + getLineLength(row, column, -11) >= winLineLength - 1);
    }

    private void checkGameState(int row, int column) {
        logger.debug(String.format("checking for win line after move [%d, %d]", row, column));
        if (isWinLineConstructed(row, column)) {
            logger.debug("win line constructed, finishing game");
            isGameEnded = true;
            gameWinner = gameField.getCellState(row, column);
            logger.debug("setting game winner to " + gameWinner);
        } else {
            logger.debug("win line was not found");
            if (moveCounter == totalMovesCount) {
                logger.debug("no free space left at the game field, ending game");
                isGameEnded = true;
            }
        }
    }

    public boolean isGameFinished() {
        return isGameEnded;
    }

    public String getGameWinner() {
        switch (gameWinner) {
            case CROSS: return "cross";
            case CIRCLE: return "circle";
            case NONE: return  "draw";
            default:
                logger.error("unknown game winner " + gameWinner);
                throw new IllegalArgumentException();
        }
    }

    public IField getField() {
        return gameField;
    }
}
TOP

Related Classes of model.GameModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.