Skip to contentMethod: hashCode()
      1: package de.fhdw.gaming.ipspiel23.c4.domain.impl;
2: 
3: import de.fhdw.gaming.ipspiel23.c4.domain.C4Direction;
4: import de.fhdw.gaming.ipspiel23.c4.domain.IC4Position;
5: import de.fhdw.gaming.ipspiel23.c4.domain.IC4Player;
6: import de.fhdw.gaming.ipspiel23.c4.domain.IC4SolutionSlim;
7: 
8: /**
9:  * The default implementation of {@link IC4SolutionSlim}.
10:  */
11: public class C4SolutionSlim implements IC4SolutionSlim {
12:     
13:     /**
14:      * The token of the player who owns this solution.
15:      */
16:     private final int token;
17: 
18:     /**
19:      * The row index of the start position.
20:      */
21:     private final int rowIndexStart;
22: 
23:     /**
24:      * The column index of the start position.
25:      */
26:     private final int columnIndexStart;
27: 
28:     /**
29:      * The row index of the end position.
30:      */
31:     private final int rowIndexEnd;
32: 
33:     /**
34:      * The column index of the end position.
35:      */
36:     private final int columnIndexEnd;
37: 
38:     /**
39:      * The parent board that contains this solution.
40:      */
41:     private final C4BoardSlim parentBoard;
42: 
43:     /**
44:      * The direction of this solution.
45:      */
46:     private final C4Direction direction;
47: 
48:     /**
49:      * The number of fields in this solution.
50:      */
51:     private final int solutionSize;
52:     
53:     /**
54:      * The lazily initialized start position.
55:      */
56:     private IC4Position startPosition;
57: 
58:     /**
59:      * The lazily initialized end position.
60:      */
61:     private IC4Position endPosition;
62:     
63:     /**
64:      * Creates a new solution.
65:      * 
66:      * @param parentBoard The parent board that contains this solution.
67:      * @param token The token of the player who owns this solution.
68:      * @param rowIndexEnd The row index of the end position.
69:      * @param columnIndexEnd The column index of the end position.
70:      * @param direction The direction of this solution, in the direction from the start position to the end position.
71:      * @param solutionSize The number of fields in this solution.
72:      */
73:     public C4SolutionSlim(final C4BoardSlim parentBoard, final int token, final int rowIndexEnd, 
74:             final int columnIndexEnd, final C4Direction direction, final int solutionSize) {
75:         this.parentBoard = parentBoard;
76:         this.solutionSize = solutionSize;
77:         this.token = token;
78:         this.rowIndexEnd = rowIndexEnd;
79:         this.columnIndexEnd = columnIndexEnd;
80:         this.direction = direction;
81:         
82:         final C4Direction inverseDirection = direction.getInverse();
83:         // -1 because the end position is already included in the solution size
84:         final int steps = solutionSize - 1;
85:         this.rowIndexStart = inverseDirection.stepFromRow(rowIndexEnd, steps);
86:         this.columnIndexStart = inverseDirection.stepFromColumn(columnIndexEnd, steps);
87:     }
88: 
89:     /**
90:      * Returns the raw column end index, without allocating a new position.
91:      */
92:     public int getColumnIndexEnd() {
93:         return columnIndexEnd;
94:     }
95: 
96:     /**
97:      * Returns the raw row end index, without allocating a new position.
98:      */
99:     public int getRowIndexEnd() {
100:         return rowIndexEnd;
101:     }
102: 
103:     @Override
104:     public IC4Player getOwner() {
105:         return this.parentBoard.getPlayerByToken(token);
106:     }
107: 
108:     @Override
109:     public IC4Position getStartPosition() {
110:         // lazy heap allocation
111:         if (this.startPosition == null) {
112:             this.startPosition = new C4Position(this.rowIndexStart, this.columnIndexStart);
113:         }
114:         return this.startPosition;
115:     }
116: 
117:     @Override
118:     public IC4Position getEndPosition() {
119:         // lazy heap allocation
120:         if (this.endPosition == null) {
121:             this.endPosition = new C4Position(this.rowIndexEnd, this.columnIndexEnd);
122:         }
123:         return this.endPosition;
124:     }
125: 
126:     @Override
127:     public int size() {
128:         return this.solutionSize;
129:     }
130: 
131:     @Override
132:     public C4Direction getDirection() {
133:         return this.direction;
134:     }
135: 
136:     @Override
137:     public boolean equals(final Object other) {
138:         if (other == null) {
139:             return false;
140:         }
141:         if (!(other instanceof IC4SolutionSlim)) {
142:             return false;
143:         }
144:         final IC4SolutionSlim otherSolution = (IC4SolutionSlim) other;
145:         return this.token == otherSolution.getOwner().getToken() 
146:             // we don't care what direction a solution is facing.
147:             // the direction itself should probably be internal, but I guess
148:             // it may have valid use cases for consumers of our library :)
149:             && (this.getStartPosition().equals(otherSolution.getStartPosition()) 
150:                     && this.getEndPosition().equals(otherSolution.getEndPosition())
151:                 || this.getStartPosition().equals(otherSolution.getEndPosition()) 
152:                     && this.getEndPosition().equals(otherSolution.getStartPosition()))
153:             && this.size() == otherSolution.size();
154:     }
155: 
156:     @Override
157:     public int hashCode() {
158:         int hash = 7 * 31;
159:         hash += this.token;
160:         hash = hash * 31 + (this.getStartPosition().hashCode() ^ this.getEndPosition().hashCode());
161:         hash = hash * 31 + this.size();
162:         return hash;
163:     }
164: 
165:     @Override
166:     public String toString() {
167:         return String.format("C4SolutionSlim: (%d, %d) -- %d -- (%d, %d)",
168:             this.rowIndexStart, this.columnIndexStart, this.token, this.rowIndexEnd, this.columnIndexEnd);
169:     }
170: }