Skip to content

Method: findAllSolutions(Set, int, int, int, boolean)

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: }