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 = 2;
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: public static final int MAX_NUMBER_OF_PLAYERS = 2;
78:
79: /**
80: * The currently specified board dimensions.
81: */
82: private final C4BoardDimensions boardDimensions;
83:
84: /**
85: * The currently specified number of tokens that need to be matched to form a solution.
86: */
87: private int solutionSize;
88:
89: /**
90: * The total number of players that will play on the board.
91: */
92: private final int playerCount;
93:
94: /**
95: * Creates a new instance of {@link C4BoardLimits}.
96: * @param playerCount the actual number of players that will play on the board
97: * @param initialRowCount the initial number of rows the board will have
98: * @param initialColumnCount the initial number of columns the board will have
99: * @param initialSolutionSize the initial number of tokens that need to be matched to form a solution
100: */
101: public C4BoardLimits(final int playerCount, final int initialRowCount,
102: final int initialColumnCount, final int initialSolutionSize) {
103: this.playerCount = playerCount;
104: this.boardDimensions = new C4BoardDimensions(initialRowCount, initialColumnCount);
105: this.solutionSize = initialSolutionSize;
106: }
107:
108: /**
109: * Returns the number of players that will play on the board.
110: */
111: public int getPlayerCount() {
112: return playerCount;
113: }
114:
115: /**
116: * Returns the number of rows the board will have.
117: */
118: public int getRowCount() {
119: return this.boardDimensions.getRowCount();
120: }
121:
122: /**
123: * Updates the number of rows the board will have to the specified value.
124: * @param rowCount the new number of rows the board will have
125: */
126: public void setRowCount(final int rowCount) {
127: this.boardDimensions.setRowCount(rowCount);
128: }
129:
130: /**
131: * Returns the number of columns the board will have.
132: */
133: public int getColumnCount() {
134: return this.boardDimensions.getColumnCount();
135: }
136:
137: /**
138: * Updates the number of columns the board will have to the specified value.
139: * @param columnCount the new number of columns the board will have
140: */
141: public void setColumnCount(final int columnCount) {
142: this.boardDimensions.setColumnCount(columnCount);
143: }
144:
145: /**
146: * Returns the number of tokens that need to be matched to form a solution.
147: */
148: public int getSolutionSize() {
149: return solutionSize;
150: }
151:
152: /**
153: * Updates the number of tokens that need to be matched to form a solution to the specified value.
154: * @param solutionSize the new number of tokens that need to be matched to form a solution
155: */
156: public void setSolutionSize(final int solutionSize) {
157: this.solutionSize = solutionSize;
158: }
159:
160: /**
161: * Checks if the current board settings comply with the board limits.
162: * @throws InputProviderException if the current board limits are invalid
163: */
164: public void assertIsValid() throws InputProviderException {
165: // validate board size
166: this.assertStaticLimits();
167: this.boardDimensions.assertStaticLimits();
168:
169: final int fieldCount = this.boardDimensions.getRowCount() * this.boardDimensions.getColumnCount();
170: // check for fieldCount > MAX_FIELD_COUNT
171: if (fieldCount < 0) { // 32 bit signed integer overflow
172: throw new InputProviderException("The board is too large: the total number of fields exceeds "
173: + "the maximum allowed value (" + MAX_FIELD_COUNT + ").");
174: }
175:
176: // validate solution size
177: // does the solution fit on the board?
178: if (this.solutionSize > Math.max(this.boardDimensions.getRowCount(), this.boardDimensions.getColumnCount())) {
179: throw new InputProviderException("The required solution size is too large: the solution size exceeds "
180: + "the number of rows and columns on the board. This is dumb.");
181: }
182: // has every player the possibility to win?
183: if (fieldCount < this.playerCount * this.solutionSize) {
184: throw new InputProviderException("The current board settings do not allow every player to win: "
185: + "the number of fields is too small to allow every player to form a solution, if players "
186: + "take turns placing tokens.");
187: }
188: }
189:
190: /**
191: * Checks if the current board settings comply with the static board limits.
192: * @throws InputProviderException if they don't comply...
193: */
194: private void assertStaticLimits() throws InputProviderException {
195: if (this.solutionSize < MIN_SOLUTION_SIZE) {
196: throw new InputProviderException("The specified solution size is too small: the solution size "
197: + "must be at least " + MIN_SOLUTION_SIZE + ".");
198: }
199: if (this.solutionSize > MAX_SOLUTION_SIZE) {
200: throw new InputProviderException("The specified solution size is too large: the solution size "
201: + "must not exceed " + MAX_SOLUTION_SIZE + ".");
202: }
203: }
204:
205: @Override
206: public boolean equals(final Object object) {
207: if (object == null) {
208: return false;
209: }
210: if (object == this) {
211: return true;
212: }
213: if (!(object instanceof C4BoardLimits)) {
214: return false;
215: }
216: final C4BoardLimits other = (C4BoardLimits) object;
217: return this.boardDimensions.equals(other.boardDimensions)
218: && this.solutionSize == other.solutionSize
219: && this.playerCount == other.playerCount;
220: }
221:
222: @Override
223: public int hashCode() {
224: int hash = 7;
225: hash = hash * 31 + this.boardDimensions.hashCode();
226: hash = hash * 31 + this.solutionSize;
227: hash = hash * 31 + this.playerCount;
228: return hash;
229: }
230: }