Skip to content

Method: scanRemaining(int, int, int)

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 horizontally (rows).
14: */
15: public class C4SolutionAnalyzerHorizontal extends C4SolutionAnalyzer {
16:
17: /**
18: * The last row which is updated while searching for a solution to
19: * speed up the search process.
20: */
21: private int optimizedRowMax;
22:
23: /**
24: * Creates a new {@link C4SolutionAnalyzerHorizontal}.
25: * @param board The board to analyze.
26: */
27: public C4SolutionAnalyzerHorizontal(final C4BoardSlim board) {
28: super(board, C4Direction.EAST);
29: optimizedRowMax = super.rowMax();
30: }
31:
32: @Override
33: public IC4SolutionSlim tryFindFirstSolution(final IC4SolutionSlim currentSolution, final boolean updateCache) {
34:
35: if (currentSolution != null) {
36: return currentSolution;
37: }
38:
39: boolean isRowEmpty = false;
40: // count row by row, EAST from bottom to top for faster matches
41: // abort as soon as we reach an empty row (gravity)
42: for (int row = this.optimizedRowMax - 1; row >= 0 && !isRowEmpty; row--) {
43: int token;
44: int lastToken = 0;
45: int count = 0;
46: isRowEmpty = true;
47: boolean isRowFull = true;
48: for (int col = 0; col < colMax(); col++, lastToken = token) {
49: token = board().getTokenUnsafe(row, col);
50: count = countConsecutivesBranchless(count, token, lastToken);
51: if (count >= targetCount()) {
52: return scanRemaining(token, row, col);
53: }
54: isRowFull &= token != EMPTY_TOKEN;
55: isRowEmpty &= token == EMPTY_TOKEN;
56: }
57: // if the current row is full and contains no solution we can remember that
58: // and don't have to re-evaluate that row next time
59: if (updateCache && isRowFull) {
60: this.optimizedRowMax = row;
61: }
62: }
63: return null;
64: }
65:
66: @Override
67: public void findAllSolutions(final Set<IC4SolutionSlim> resultSet, final boolean updateCache) {
68: // count row by row, EAST from bottom to top for faster matches
69: boolean isRowEmpty = false;
70: for (int row = this.optimizedRowMax - 1; row >= 0 && !isRowEmpty; row--) {
71: isRowEmpty = true;
72: int token;
73: int lastToken = 0;
74: int count = 0;
75: boolean isRowFull = true;
76: boolean rowContainsSolution = false;
77: int col = 0;
78: for (; col < colMax(); col++, lastToken = token) {
79: token = board().getTokenUnsafe(row, col);
80: count = countConsecutivesBranchless(count, token, lastToken);
81: if (count >= targetCount()) {
82: count = 0;
83: final C4SolutionSlim solution = scanRemaining(token, row, col);
84: resultSet.add(solution);
85: rowContainsSolution = true;
86: // skip to the end of the solution
87: col = solution.getColumnIndexEnd();
88: }
89: isRowFull &= token != EMPTY_TOKEN;
90: isRowEmpty &= token == EMPTY_TOKEN;
91: }
92: // if the current row is full and contains no solution we can remember that
93: // and don't have to re-evaluate that row the next time
94: if (updateCache && isRowFull && !rowContainsSolution) {
95: this.optimizedRowMax = row;
96: }
97: }
98: }
99:
100: @Override
101: protected C4SolutionSlim scanRemaining(final int token, final int startRow, final int startCol) {
102: int col = startCol + 1;
103:• while (col < colMax() && board().getTokenUnsafe(startRow, col) == token) {
104: col++;
105: }
106: // revert last change to get inclusive upper bound
107: col--;
108: return solutionOf(token, startRow, col, board().getMinimumSolutionSize() + col - startCol);
109: }
110:
111: @Override
112: public void resetCache() {
113: this.optimizedRowMax = super.rowMax();
114: }
115: }