Skip to content

Package: OthelloStateImpl

OthelloStateImpl

nameinstructionbranchcomplexitylinemethod
OthelloStateImpl(OthelloBoard, OthelloPlayer, OthelloPlayer, boolean)
M: 0 C: 89
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 16
100%
M: 0 C: 1
100%
OthelloStateImpl(OthelloStateImpl)
M: 0 C: 34
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
computeNextPlayers()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
deepCopy()
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
equals(Object)
M: 0 C: 40
100%
M: 0 C: 12
100%
M: 0 C: 7
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
gameOver()
M: 0 C: 45
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 11
100%
M: 0 C: 1
100%
getBlackPlayer()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getBoard()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getCurrentPlayer()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getNumberOfConsecutiveSkips()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getOtherPlayer()
M: 0 C: 9
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getPlayers()
M: 0 C: 22
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getWhitePlayer()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
hashCode()
M: 0 C: 31
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
isBlackPlayerCurrent()
M: 0 C: 9
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
moveCompleted(boolean)
M: 0 C: 19
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
nextTurn()
M: 0 C: 11
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
toString()
M: 0 C: 36
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%

Coverage

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.GameException;
28: import de.fhdw.gaming.core.domain.PlayerState;
29: import de.fhdw.gaming.othello.core.domain.OthelloBoard;
30: import de.fhdw.gaming.othello.core.domain.OthelloFieldState;
31: import de.fhdw.gaming.othello.core.domain.OthelloPlayer;
32: import de.fhdw.gaming.othello.core.domain.OthelloState;
33:
34: /**
35: * Implements {@link OthelloState}.
36: */
37: @SuppressWarnings("PMD.GodClass")
38: final class OthelloStateImpl implements OthelloState {
39:
40: /**
41: * The board.
42: */
43: private final OthelloBoard board;
44: /**
45: * The player using the black tokens.
46: */
47: private final OthelloPlayer blackPlayer;
48: /**
49: * The player using the white tokens.
50: */
51: private final OthelloPlayer whitePlayer;
52: /**
53: * The current player.
54: */
55: private OthelloPlayer currentPlayer;
56: /**
57: * The number of consecutive skips.
58: */
59: private int numberOfConsecutiveSkips;
60:
61: /**
62: * Creates an Othello state.
63: *
64: * @param board The board.
65: * @param blackPlayer The player using the black tokens.
66: * @param whitePlayer The player using the white tokens.
67: * @param blackIsNext {@code true} if black is next, else white is next.
68: * @throws GameException if the state cannot be created according to the rules of the game.
69: */
70: OthelloStateImpl(final OthelloBoard board, final OthelloPlayer blackPlayer, final OthelloPlayer whitePlayer,
71: final boolean blackIsNext) throws GameException {
72:
73: this.board = Objects.requireNonNull(board, "board");
74: this.blackPlayer = Objects.requireNonNull(blackPlayer, "blackPlayerBuilder");
75: this.whitePlayer = Objects.requireNonNull(whitePlayer, "whitePlayerBuilder");
76:• this.currentPlayer = blackIsNext ? this.blackPlayer : this.whitePlayer;
77: this.numberOfConsecutiveSkips = 0;
78:
79:• if (!this.blackPlayer.isUsingBlackTokens()) {
80: throw new IllegalArgumentException(
81: String.format("Black player %s does not use black tokens.", this.blackPlayer));
82: }
83:• if (this.whitePlayer.isUsingBlackTokens()) {
84: throw new IllegalArgumentException(
85: String.format("White player %s does not use white tokens.", this.whitePlayer));
86: }
87:• if (this.blackPlayer.getName().equals(this.whitePlayer.getName())) {
88: throw new IllegalArgumentException(
89: String.format("Both players have the same name '%s'.", this.blackPlayer.getName()));
90: }
91: }
92:
93: /**
94: * Creates an Othello state by copying an existing one.
95: *
96: * @param source The state to copy.
97: */
98: OthelloStateImpl(final OthelloStateImpl source) {
99: this.board = source.board.deepCopy();
100: this.blackPlayer = source.blackPlayer.deepCopy();
101: this.whitePlayer = source.whitePlayer.deepCopy();
102:• this.currentPlayer = source.isBlackPlayerCurrent() ? this.blackPlayer : this.whitePlayer;
103: this.numberOfConsecutiveSkips = source.numberOfConsecutiveSkips;
104: }
105:
106: @Override
107: public String toString() {
108: return String.format(
109: "OthelloState[board=%s, blackPlayer=%s, whitePlayer=%s, currentPlayer=%s, numberOfConsecutiveSkips=%d]",
110: this.board,
111: this.blackPlayer,
112: this.whitePlayer,
113:• this.currentPlayer.isUsingBlackTokens() ? OthelloFieldState.BLACK : OthelloFieldState.WHITE,
114: this.numberOfConsecutiveSkips);
115: }
116:
117: @Override
118: public boolean equals(final Object obj) {
119:• if (obj instanceof OthelloStateImpl) {
120: final OthelloStateImpl other = (OthelloStateImpl) obj;
121:• return this.board.equals(other.board) && this.blackPlayer.equals(other.blackPlayer)
122:• && this.whitePlayer.equals(other.whitePlayer)
123:• && this.isBlackPlayerCurrent() == other.isBlackPlayerCurrent()
124: && this.numberOfConsecutiveSkips == other.numberOfConsecutiveSkips;
125: }
126: return false;
127: }
128:
129: @Override
130: public int hashCode() {
131: return Objects.hash(
132: this.board,
133: this.blackPlayer,
134: this.whitePlayer,
135: this.isBlackPlayerCurrent(),
136: this.numberOfConsecutiveSkips);
137: }
138:
139: @Override
140: public OthelloStateImpl deepCopy() {
141: return new OthelloStateImpl(this);
142: }
143:
144: @Override
145: public Map<String, OthelloPlayer> getPlayers() {
146: final Map<String, OthelloPlayer> result = new LinkedHashMap<>();
147: result.put(this.blackPlayer.getName(), this.blackPlayer);
148: result.put(this.whitePlayer.getName(), this.whitePlayer);
149: return result;
150: }
151:
152: @Override
153: public OthelloBoard getBoard() {
154: return this.board;
155: }
156:
157: @Override
158: public OthelloPlayer getBlackPlayer() {
159: return this.blackPlayer;
160: }
161:
162: @Override
163: public OthelloPlayer getWhitePlayer() {
164: return this.whitePlayer;
165: }
166:
167: @Override
168: public OthelloPlayer getCurrentPlayer() {
169: return this.currentPlayer;
170: }
171:
172: @Override
173: public void moveCompleted(final boolean skipMove) {
174:• if (skipMove) {
175: ++this.numberOfConsecutiveSkips;
176:• if (this.numberOfConsecutiveSkips > 1) {
177: this.gameOver();
178: }
179: } else {
180: this.numberOfConsecutiveSkips = 0;
181: }
182: }
183:
184: @Override
185: public int getNumberOfConsecutiveSkips() {
186: return this.numberOfConsecutiveSkips;
187: }
188:
189: @Override
190: public Set<OthelloPlayer> computeNextPlayers() {
191: return Collections.singleton(this.currentPlayer);
192: }
193:
194: @Override
195: public void nextTurn() {
196: this.currentPlayer = this.getOtherPlayer();
197:• if (this.numberOfConsecutiveSkips > 1) {
198: this.gameOver();
199: }
200: }
201:
202: /**
203: * Returns the currently inactive player.
204: */
205: private OthelloPlayer getOtherPlayer() {
206:• if (this.isBlackPlayerCurrent()) {
207: return this.whitePlayer;
208: } else {
209: return this.blackPlayer;
210: }
211: }
212:
213: /**
214: * Returns {@code true} iff the current player uses black tokens.
215: */
216: @SuppressWarnings("PMD.CompareObjectsWithEquals")
217: private boolean isBlackPlayerCurrent() {
218:• return this.currentPlayer == this.blackPlayer;
219: }
220:
221: /**
222: * Updates the player states after the game has finished.
223: */
224: private void gameOver() {
225: final int blackTokens = this.board.getFieldsBeing(OthelloFieldState.BLACK).size();
226: final int whiteTokens = this.board.getFieldsBeing(OthelloFieldState.WHITE).size();
227:• if (blackTokens > whiteTokens) {
228: this.blackPlayer.setState(PlayerState.WON);
229: this.whitePlayer.setState(PlayerState.LOST);
230:• } else if (blackTokens < whiteTokens) {
231: this.blackPlayer.setState(PlayerState.LOST);
232: this.whitePlayer.setState(PlayerState.WON);
233: } else {
234: this.blackPlayer.setState(PlayerState.DRAW);
235: this.whitePlayer.setState(PlayerState.DRAW);
236: }
237: }
238: }