Skip to content

Method: getBoard()

1: /*
2: * Copyright © 2020 Fachhochschule für die Wirtschaft (FHDW) Hannover
3: *
4: * This file is part of othello-core.
5: *
6: * Othello-core is free software: you can redistribute it and/or modify it under
7: * the terms of the GNU General Public License as published by the Free Software
8: * Foundation, either version 3 of the License, or (at your option) any later
9: * version.
10: *
11: * Othello-core is distributed in the hope that it will be useful, but WITHOUT
12: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14: * details.
15: *
16: * You should have received a copy of the GNU General Public License along with
17: * othello-core. If not, see <http://www.gnu.org/licenses/>.
18: */
19: package de.fhdw.gaming.othello.core.domain.impl;
20:
21: import java.util.Collections;
22: import java.util.LinkedHashMap;
23: import java.util.Map;
24: import java.util.Objects;
25: import java.util.Set;
26:
27: import de.fhdw.gaming.core.domain.PlayerState;
28: import de.fhdw.gaming.othello.core.domain.OthelloBoard;
29: import de.fhdw.gaming.othello.core.domain.OthelloFieldState;
30: import de.fhdw.gaming.othello.core.domain.OthelloPlayer;
31: import de.fhdw.gaming.othello.core.domain.OthelloState;
32:
33: /**
34: * Implements {@link OthelloState}.
35: */
36: @SuppressWarnings("PMD.GodClass")
37: final class OthelloStateImpl implements OthelloState {
38:
39: /**
40: * The board.
41: */
42: private final OthelloBoard board;
43: /**
44: * The player using the black tokens.
45: */
46: private final OthelloPlayer blackPlayer;
47: /**
48: * The player using the white tokens.
49: */
50: private final OthelloPlayer whitePlayer;
51: /**
52: * The current player.
53: */
54: private OthelloPlayer currentPlayer;
55: /**
56: * The number of consecutive skips.
57: */
58: private int numberOfConsecutiveSkips;
59:
60: /**
61: * Creates an Othello state.
62: *
63: * @param board The board.
64: * @param blackPlayer The player using the black tokens.
65: * @param whitePlayer The player using the white tokens.
66: * @param blackIsNext {@code true} if black is next, else white is next.
67: */
68: OthelloStateImpl(final OthelloBoard board, final OthelloPlayer blackPlayer, final OthelloPlayer whitePlayer,
69: final boolean blackIsNext) {
70:
71: this.board = Objects.requireNonNull(board, "board");
72: this.blackPlayer = Objects.requireNonNull(blackPlayer, "blackPlayerBuilder");
73: this.whitePlayer = Objects.requireNonNull(whitePlayer, "whitePlayerBuilder");
74: this.currentPlayer = blackIsNext ? this.blackPlayer : this.whitePlayer;
75: this.numberOfConsecutiveSkips = 0;
76:
77: if (!this.blackPlayer.isUsingBlackTokens()) {
78: throw new IllegalArgumentException(
79: String.format("Black player %s does not use black tokens.", this.blackPlayer));
80: }
81: if (this.whitePlayer.isUsingBlackTokens()) {
82: throw new IllegalArgumentException(
83: String.format("White player %s does not use white tokens.", this.whitePlayer));
84: }
85: if (this.blackPlayer.getName().equals(this.whitePlayer.getName())) {
86: throw new IllegalArgumentException(
87: String.format("Both players have the same name '%s'.", this.blackPlayer.getName()));
88: }
89: }
90:
91: /**
92: * Creates an Othello state by copying an existing one.
93: *
94: * @param source The state to copy.
95: */
96: OthelloStateImpl(final OthelloStateImpl source) {
97: this.board = source.board.deepCopy();
98: this.blackPlayer = source.blackPlayer.deepCopy();
99: this.whitePlayer = source.whitePlayer.deepCopy();
100: this.currentPlayer = source.isBlackPlayerCurrent() ? this.blackPlayer : this.whitePlayer;
101: this.numberOfConsecutiveSkips = source.numberOfConsecutiveSkips;
102: }
103:
104: @Override
105: public String toString() {
106: return String.format(
107: "OthelloState[board=%s, blackPlayer=%s, whitePlayer=%s, currentPlayer=%s, numberOfConsecutiveSkips=%d]",
108: this.board,
109: this.blackPlayer,
110: this.whitePlayer,
111: this.currentPlayer.isUsingBlackTokens() ? OthelloFieldState.BLACK : OthelloFieldState.WHITE,
112: this.numberOfConsecutiveSkips);
113: }
114:
115: @Override
116: public boolean equals(final Object obj) {
117: if (obj instanceof OthelloStateImpl) {
118: final OthelloStateImpl other = (OthelloStateImpl) obj;
119: return this.board.equals(other.board) && this.blackPlayer.equals(other.blackPlayer)
120: && this.whitePlayer.equals(other.whitePlayer)
121: && this.isBlackPlayerCurrent() == other.isBlackPlayerCurrent()
122: && this.numberOfConsecutiveSkips == other.numberOfConsecutiveSkips;
123: }
124: return false;
125: }
126:
127: @Override
128: public int hashCode() {
129: return Objects.hash(
130: this.board,
131: this.blackPlayer,
132: this.whitePlayer,
133: this.isBlackPlayerCurrent(),
134: this.numberOfConsecutiveSkips);
135: }
136:
137: @Override
138: public OthelloStateImpl deepCopy() {
139: return new OthelloStateImpl(this);
140: }
141:
142: @Override
143: public Map<String, OthelloPlayer> getPlayers() {
144: final Map<String, OthelloPlayer> result = new LinkedHashMap<>();
145: result.put(this.blackPlayer.getName(), this.blackPlayer);
146: result.put(this.whitePlayer.getName(), this.whitePlayer);
147: return result;
148: }
149:
150: @Override
151: public OthelloBoard getBoard() {
152: return this.board;
153: }
154:
155: @Override
156: public OthelloPlayer getBlackPlayer() {
157: return this.blackPlayer;
158: }
159:
160: @Override
161: public OthelloPlayer getWhitePlayer() {
162: return this.whitePlayer;
163: }
164:
165: @Override
166: public OthelloPlayer getCurrentPlayer() {
167: return this.currentPlayer;
168: }
169:
170: @Override
171: public void moveCompleted(final boolean skipMove) {
172: if (skipMove) {
173: ++this.numberOfConsecutiveSkips;
174: if (this.numberOfConsecutiveSkips > 1) {
175: this.gameOver();
176: }
177: } else {
178: this.numberOfConsecutiveSkips = 0;
179: }
180: }
181:
182: @Override
183: public int getNumberOfConsecutiveSkips() {
184: return this.numberOfConsecutiveSkips;
185: }
186:
187: @Override
188: public Set<OthelloPlayer> computeNextPlayers() {
189: return Collections.singleton(this.currentPlayer);
190: }
191:
192: @Override
193: public void nextTurn() {
194: this.currentPlayer = this.getOtherPlayer();
195: if (this.numberOfConsecutiveSkips > 1) {
196: this.gameOver();
197: }
198: }
199:
200: /**
201: * Returns the currently inactive player.
202: */
203: private OthelloPlayer getOtherPlayer() {
204: if (this.isBlackPlayerCurrent()) {
205: return this.whitePlayer;
206: } else {
207: return this.blackPlayer;
208: }
209: }
210:
211: /**
212: * Returns {@code true} iff the current player uses black tokens.
213: */
214: @SuppressWarnings("PMD.CompareObjectsWithEquals")
215: private boolean isBlackPlayerCurrent() {
216: return this.currentPlayer == this.blackPlayer;
217: }
218:
219: /**
220: * Updates the player states after the game has finished.
221: */
222: private void gameOver() {
223: final int blackTokens = this.board.getFieldsBeing(OthelloFieldState.BLACK).size();
224: final int whiteTokens = this.board.getFieldsBeing(OthelloFieldState.WHITE).size();
225: if (blackTokens > whiteTokens) {
226: this.blackPlayer.setState(PlayerState.WON);
227: this.whitePlayer.setState(PlayerState.LOST);
228: } else if (blackTokens < whiteTokens) {
229: this.blackPlayer.setState(PlayerState.LOST);
230: this.whitePlayer.setState(PlayerState.WON);
231: } else {
232: this.blackPlayer.setState(PlayerState.DRAW);
233: this.whitePlayer.setState(PlayerState.DRAW);
234: }
235: }
236: }