Package: C4SolutionAnalyzerDiagonalRight
C4SolutionAnalyzerDiagonalRight
| name | instruction | branch | complexity | line | method | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| C4SolutionAnalyzerDiagonalRight(C4BoardSlim) | 
  | 
  | 
  | 
  | 
  | 
||||||||||||||||||||
| findAllSolutions(Set, boolean) | 
  | 
  | 
  | 
  | 
  | 
||||||||||||||||||||
| findAllSolutions(Set, int, int, int, boolean) | 
  | 
  | 
  | 
  | 
  | 
||||||||||||||||||||
| scanRemaining(int, int, int) | 
  | 
  | 
  | 
  | 
  | 
||||||||||||||||||||
| tryFindFirstSolution(IC4SolutionSlim, boolean) | 
  | 
  | 
  | 
  | 
  | 
||||||||||||||||||||
| tryFindFirstSolution(int, int, int, boolean) | 
  | 
  | 
  | 
  | 
  | 
||||||||||||||||||||
Coverage
1: package de.fhdw.gaming.ipspiel23.c4.domain.impl.evaluation;
2: 
3: import java.util.Set;
4: 
5: import de.fhdw.gaming.ipspiel23.c4.domain.C4Direction;
6: import de.fhdw.gaming.ipspiel23.c4.domain.IC4SolutionSlim;
7: import de.fhdw.gaming.ipspiel23.c4.domain.impl.C4BoardSlim;
8: import de.fhdw.gaming.ipspiel23.c4.domain.impl.C4SolutionSlim;
9: 
10: import static de.fhdw.gaming.ipspiel23.c4.domain.impl.C4BoardSlim.EMPTY_TOKEN;
11: 
12: /**
13:  * A {@link C4SolutionAnalyzer} that analyzes the board on the diagonal from the top left to the bottom right.
14:  */
15: public class C4SolutionAnalyzerDiagonalRight extends C4SolutionAnalyzerDiagonal {
16: 
17:     /**
18:      * Creates a new {@link C4SolutionAnalyzerDiagonalRight}.
19:      * @param board The board to analyze.
20:      */
21:     public C4SolutionAnalyzerDiagonalRight(final C4BoardSlim board) {
22:         super(board, C4Direction.NORTH_WEST);
23:     }
24: 
25:     @Override
26:     public IC4SolutionSlim tryFindFirstSolution(final IC4SolutionSlim currentSolution, final boolean updateCache) {
27:         // "Assignment of parameter 'currentSolution' is not allowed." :P
28:         IC4SolutionSlim solution = currentSolution;
29:         
30:         int iteration = 0;
31:         // determine start row of the last column (skip first targetCount rows as the will never contain a solution)
32:•        for (int startRow = targetCount(); solution == null && startRow < rowMax(); startRow++, iteration++) {
33:•            if (mayContainSolution(iteration)) {
34:                 solution = tryFindFirstSolution(startRow, colMax() - 1, iteration, updateCache);
35:             }
36:         }
37:         // determine start column of last row (ignore first targetCount columns as the will never contain a solution)
38:         // don't evaluate diagonal starting in bottom right twice (startCol = colMax - 2)
39:•        for (int startCol = colMax() - 2; solution == null && startCol >= targetCount(); startCol--, iteration++) {
40:•            if (mayContainSolution(iteration)) {
41:                 solution = tryFindFirstSolution(rowMax() - 1, startCol, iteration, updateCache);
42:             }
43:         }
44:         return solution;
45:     }
46:     
47:     /**
48:      * Lazily searches for the first solution on the board starting at the specified position.
49:      * @param startRow the row to start at
50:      * @param startCol the column to start at
51:      * @param iteration the current iteration of the search
52:      * @param updateCache whether to update the solution cache, preventing the same line to be checked again
53:      * @return The first solution on the board or null if no solution was found.
54:      */
55:     private IC4SolutionSlim tryFindFirstSolution(final int startRow, final int startCol, 
56:             final int iteration, final boolean updateCache) {
57:         int count = 0;
58:         int lastToken = 0;
59:         boolean isDiagonalFull = true;
60:         // "ForLoopVariableCount: Too many control variables in the for statement" :P
61:         int row = startRow;
62:         int col = startCol;
63:•        for (; row >= 0 && col >= 0; row--, col--) {
64:             final int token = board().getTokenUnsafe(row, col);
65:             count = countConsecutivesBranchless(count, token, lastToken);
66:•            if (count >= targetCount()) {
67:                 return scanRemaining(token, row, col);
68:             }
69:•            isDiagonalFull &= token != EMPTY_TOKEN;
70:             lastToken = token;
71:         }
72:•        if (updateCache && isDiagonalFull) {
73:             noSolutionIn(iteration);
74:         }
75:         return null;
76:     }
77: 
78:     @Override
79:     public void findAllSolutions(final Set<IC4SolutionSlim> resultSet, final boolean updateCache) {
80:         int iteration = 0;
81:         // determine start row of the last column (skip first targetCount rows)
82:•        for (int startRow = targetCount(); startRow < rowMax(); startRow++, iteration++) {
83:•            if (mayContainSolution(iteration)) {
84:                 findAllSolutions(resultSet, startRow, colMax() - 1, iteration, updateCache);
85:             }
86:         }
87:         // determine start column of last row (ignore first targetCount columns)
88:         // don't evaluate diagonal starting in bottom right twice (startCol = colMax - 2)
89:•        for (int startCol = colMax() - 2; startCol >= targetCount(); startCol--, iteration++) {
90:•            if (mayContainSolution(iteration)) {
91:                 findAllSolutions(resultSet, rowMax() - 1, startCol, iteration, updateCache);
92:             }
93:         }
94:     }
95:     
96:     /**
97:      * Eagerly searches for all solutions on the board starting at the specified position.
98:      * @param resultSet the set to which any solutions are added
99:      * @param startRow the row to start at
100:      * @param startCol the column to start at
101:      * @param iteration the current iteration of the search
102:      * @param updateCache whether to update the solution cache, preventing the same line to be checked again
103:      */
104:     private void findAllSolutions(final Set<IC4SolutionSlim> resultSet, final int startRow,
105:             final int startCol, final int iteration, final boolean updateCache) {
106:         int count = 0;
107:         int lastToken = 0;
108:         boolean isDiagonalFull = true;
109:         boolean diagonalContainsSolution = false;
110:         // "ForLoopVariableCount: Too many control variables in the for statement" :P
111:         int row = startRow;
112:         int col = startCol;
113:•        for (; row >= 0 && col >= 0; row--, col--) {
114:             final int token = board().getTokenUnsafe(row, col);
115:             count = countConsecutivesBranchless(count, token, lastToken);
116:•            if (count >= targetCount()) {
117:                 count = 0;
118:                 final C4SolutionSlim solution = scanRemaining(token, row, col);
119:                 resultSet.add(solution);
120:                 diagonalContainsSolution = true;
121:                 // skip to end of solution
122:                 row = solution.getRowIndexEnd();
123:                 col = solution.getColumnIndexEnd();
124:             }
125:•            isDiagonalFull &= token != EMPTY_TOKEN;
126:             lastToken = token;
127:         }
128:•        if (updateCache && isDiagonalFull && !diagonalContainsSolution) {
129:             noSolutionIn(iteration);
130:         }
131:     }
132: 
133:     @Override
134:     protected C4SolutionSlim scanRemaining(final int token, final int startRow, final int startCol) {
135:         int row = startRow - 1;
136:         int col = startCol - 1;
137:•        while (row >= 0 && col >= 0 && board().getTokenUnsafe(row, col) == token) {
138:             row--; 
139:             col--;
140:         }
141:         // revert last change to get inclusive upper bound
142:         row++;
143:         col++;
144:         return solutionOf(token, row, col, board().getMinimumSolutionSize() + startRow - row);
145:     }
146: }