Skip to content

Method: hashCode()

1: package de.fhdw.gaming.ipspiel23.c4.domain.impl.validation;
2:
3: import de.fhdw.gaming.core.ui.InputProviderException;
4:
5: /**
6: * Represents the absolute limits, and currently set dimensions of a Connect-N board.
7: * User-provided values are stored in this class, and validated against the limits.
8: */
9: public class C4BoardLimits {
10:
11: /**
12: * The minimum number of rows a board must have.
13: */
14: // for the incredible "Connect Two" experience where the first player wins by default after the second move :)
15: public static final int MIN_ROW_COUNT = 2;
16:
17: /**
18: * The minimum number of columns a board must have.
19: */
20: // for the incredible "Connect Two" experience where the first player wins by default after the second move :)
21: public static final int MIN_COLUMN_COUNT = 2;
22:
23: /**
24: * The maximum number of rows a board can have.
25: */
26: // these are theoretical maximums. In the end, actualColumnCount * actualRowCount must be <= MAX_FIELD_COUNT
27: public static final int MAX_ROW_COUNT = Integer.MAX_VALUE / MIN_COLUMN_COUNT;
28:
29: /**
30: * The maximum number of columns a board can have.
31: */
32: // these are theoretical maximums. In the end, actualColumnCount * actualRowCount must be <= MAX_FIELD_COUNT
33: public static final int MAX_COLUMN_COUNT = Integer.MAX_VALUE / MIN_ROW_COUNT;
34:
35: /**
36: * The maximum number of fields a board can have.
37: */
38: // we use 32 bit indices for our internal token-state array, so if more than 4 * 2^31 - 1 = 8 GiB of RAM are
39: // available we can use the whole 31 bit range for indexing (also: why doesn't java have unsigned integers???).
40: // fun fact:
41: // at 1 second per move a draw could actually happen within our life time at
42: // just over 68 Years of 24/7 exciting Connect-N gameplay :)
43: public static final int MAX_FIELD_COUNT = Integer.MAX_VALUE;
44:
45: /**
46: * The minimum allowed number that can be set as the number of tokens that need to be matched to form a solution.
47: */
48: // "Connect One" wouldn't be too exciting TBH. Also I don't think our board-state-validation algorithm would
49: // support it.
50: public static final int MIN_SOLUTION_SIZE = 2;
51:
52: /**
53: * The maximum allowed number that can be set as the number of tokens that need to be matched to form a solution.
54: */
55: // Its probably a good idea to keep the solution size below the maximum theoretical board boundaries
56: public static final int MAX_SOLUTION_SIZE = Math.max(MAX_ROW_COUNT, MAX_COLUMN_COUNT);
57:
58: /**
59: * The minimum number of players that can play on a board.
60: */
61: // to me it's questionable how exciting a Connect Four game with a single player would be,
62: // but who am I to judge what gets other people thrilled ¯\_(ツ)_/¯
63: public static final int MIN_NUMBER_OF_PLAYERS = 1;
64:
65: /**
66: * The maximum number of players that can play on a board.
67: */
68: // let's assume we actually want each player to have at least the theoretical possibility to win
69: // fun fact:
70: // at the theoretical maximum we would still would support 33.5 times more players than RGB24 has colors available
71: // to differentiate between the pieces :P
72: // so the GUI team would have to start playing around with the alpha channel in RGB32 to give every player a unique
73: // color.
74: // also: assuming 16:9 aspect ratio you'd have to own at least a 30897x17379 px monitor to display the whole board
75: // at once, so a 32k display would *just* not suffice at "only" 30720x17280 px :)
76: public static final int MAX_NUMBER_OF_PLAYERS = C4BoardLimits.MAX_FIELD_COUNT / C4BoardLimits.MIN_SOLUTION_SIZE;
77:
78: /**
79: * The currently specified board dimensions.
80: */
81: private final C4BoardDimensions boardDimensions;
82:
83: /**
84: * The currently specified number of tokens that need to be matched to form a solution.
85: */
86: private int solutionSize;
87:
88: /**
89: * The total number of players that will play on the board.
90: */
91: private final int playerCount;
92:
93: /**
94: * Creates a new instance of {@link C4BoardLimits}.
95: * @param playerCount the actual number of players that will play on the board
96: * @param initialRowCount the initial number of rows the board will have
97: * @param initialColumnCount the initial number of columns the board will have
98: * @param initialSolutionSize the initial number of tokens that need to be matched to form a solution
99: */
100: public C4BoardLimits(final int playerCount, final int initialRowCount,
101: final int initialColumnCount, final int initialSolutionSize) {
102: this.playerCount = playerCount;
103: this.boardDimensions = new C4BoardDimensions(initialRowCount, initialColumnCount);
104: this.solutionSize = initialSolutionSize;
105: }
106:
107: /**
108: * Returns the number of players that will play on the board.
109: */
110: public int getPlayerCount() {
111: return playerCount;
112: }
113:
114: /**
115: * Returns the number of rows the board will have.
116: */
117: public int getRowCount() {
118: return this.boardDimensions.getRowCount();
119: }
120:
121: /**
122: * Updates the number of rows the board will have to the specified value.
123: * @param rowCount the new number of rows the board will have
124: */
125: public void setRowCount(final int rowCount) {
126: this.boardDimensions.setRowCount(rowCount);
127: }
128:
129: /**
130: * Returns the number of columns the board will have.
131: */
132: public int getColumnCount() {
133: return this.boardDimensions.getColumnCount();
134: }
135:
136: /**
137: * Updates the number of columns the board will have to the specified value.
138: * @param columnCount the new number of columns the board will have
139: */
140: public void setColumnCount(final int columnCount) {
141: this.boardDimensions.setColumnCount(columnCount);
142: }
143:
144: /**
145: * Returns the number of tokens that need to be matched to form a solution.
146: */
147: public int getSolutionSize() {
148: return solutionSize;
149: }
150:
151: /**
152: * Updates the number of tokens that need to be matched to form a solution to the specified value.
153: * @param solutionSize the new number of tokens that need to be matched to form a solution
154: */
155: public void setSolutionSize(final int solutionSize) {
156: this.solutionSize = solutionSize;
157: }
158:
159: /**
160: * Checks if the current board settings comply with the board limits.
161: * @throws InputProviderException if the current board limits are invalid
162: */
163: public void assertIsValid() throws InputProviderException {
164: // validate board size
165: this.assertStaticLimits();
166: this.boardDimensions.assertStaticLimits();
167:
168: final int fieldCount = this.boardDimensions.getRowCount() * this.boardDimensions.getColumnCount();
169: // check for fieldCount > MAX_FIELD_COUNT
170: if (fieldCount < 0) { // 32 bit signed integer overflow
171: throw new InputProviderException("The board is too large: the total number of fields exceeds "
172: + "the maximum allowed value (" + MAX_FIELD_COUNT + ").");
173: }
174:
175: // validate solution size
176: // does the solution fit on the board?
177: if (this.solutionSize > Math.max(this.boardDimensions.getRowCount(), this.boardDimensions.getColumnCount())) {
178: throw new InputProviderException("The required solution size is too large: the solution size exceeds "
179: + "the number of rows and columns on the board. This is dumb.");
180: }
181: // has every player the possibility to win?
182: if (fieldCount < this.playerCount * this.solutionSize) {
183: throw new InputProviderException("The current board settings do not allow every player to win: "
184: + "the number of fields is too small to allow every player to form a solution, if players "
185: + "take turns placing tokens.");
186: }
187: }
188:
189: /**
190: * Checks if the current board settings comply with the static board limits.
191: * @throws InputProviderException if they don't comply...
192: */
193: private void assertStaticLimits() throws InputProviderException {
194: if (this.solutionSize < MIN_SOLUTION_SIZE) {
195: throw new InputProviderException("The specified solution size is too small: the solution size "
196: + "must be at least " + MIN_SOLUTION_SIZE + ".");
197: }
198: if (this.solutionSize > MAX_SOLUTION_SIZE) {
199: throw new InputProviderException("The specified solution size is too large: the solution size "
200: + "must not exceed " + MAX_SOLUTION_SIZE + ".");
201: }
202: }
203:
204: @Override
205: public boolean equals(final Object object) {
206: if (object == null) {
207: return false;
208: }
209: if (object == this) {
210: return true;
211: }
212: if (!(object instanceof C4BoardLimits)) {
213: return false;
214: }
215: final C4BoardLimits other = (C4BoardLimits) object;
216: return this.boardDimensions.equals(other.boardDimensions)
217: && this.solutionSize == other.solutionSize
218: && this.playerCount == other.playerCount;
219: }
220:
221: @Override
222: public int hashCode() {
223: int hash = 7;
224: hash = hash * 31 + this.boardDimensions.hashCode();
225: hash = hash * 31 + this.solutionSize;
226: hash = hash * 31 + this.playerCount;
227: return hash;
228: }
229: }