class BoardManipulator { private ColorGrid cg; private ColorGridRenderer cgr; private int srow, scol; private boolean wrap; private color[] tileQueue; BoardManipulator(ColorGridRenderer cgr) { this.cgr = cgr; cg = cgr.getColorGrid(); wrap = true; srow = scol = 0; tileQueue = new color[0]; syncCGR(); } // ***************************************** // ** Selection Manipulation // ***************************************** // give this manipulator focus void focus() { cgr.showBorder(true); } // remove focus void unfocus() { cgr.showBorder(false); } // causes the selection box to wrap around left/right top/bottom void wrapSelection(boolean b) { wrap = b; } void setSelectionColor(color c) { cg.set(srow, scol, c); } color getSelectionColor() { return cg.get(srow, scol); } GridSpace getSelectionLoc() { return new GridSpace(srow, scol); } void moveSelectionLeft() { scol--; if ( wrap && scol < 0 ) { scol = cg.cols() - 1; } else if ( scol < 0 ) { scol = 0; } syncCGR(); } void moveSelectionRight() { scol++; if ( wrap && scol >= cg.cols() ) { scol = 0; } else if ( scol >= cg.cols() ) { scol = cg.cols() - 1; } syncCGR(); } void moveSelectionUp() { srow--; if ( wrap && srow < 0 ) { srow = cg.rows() - 1; } else if ( srow < 0 ) { srow = 0; } syncCGR(); } void moveSelectionDown() { srow++; if ( wrap && srow >= cg.rows() ) { srow = 0; } else if ( srow >= cg.rows() ) { srow = cg.rows() - 1; } syncCGR(); } private void syncCGR() { cgr.setSelection(srow, scol); } // ******************************************* // ** Match testing // ******************************************* // takes the color to use as a match key // returns a list of the positions that have been cleared ArrayList findMatches(color match) { ArrayList cleared = new ArrayList(); for (int r = 0; r < cg.rows(); r++) { for (int c = 0; c < cg.cols(); c++) { color first = cg.get(r, c); if ( colorsMatch(match, first) ) { int matches = 1; // look right for(int skip = 1; r + skip < cg.rows(); skip++) { // look at the next color, if it matches, increment matches color next = cg.get(r+skip, c); if ( colorsMatch(first, next) ) { //println("Found match at " + (r+skip) + " " + c); matches++; } else { // no match, stop looking break; } } // if there are three or more matches, clear them if ( matches > 2 ) { for(int i = 0; i < matches; i++) { // if the space hasn't been cleared // clear it and increment totalCleared if ( !isCleared(r+i, c) ) { clearSpace(r+i, c); cleared.add( new GridSpace(r+i, c) ); } } } // look down matches = 1; for(int skip = 1; c + skip < cg.cols(); skip++) { // look at the next color, if it matches, increment matches color next = cg.get(r, c + skip); if ( colorsMatch(first, next) ) { //println("Found match at " + r + " " + (c+skip)); matches++; } else { // no match, stop looking break; } } // if there are three or more matches, clear them if ( matches > 2 ) { for(int i = 0; i < matches; i++) { // if the space hasn't been cleared // clear it and increment totalCleared if ( !isCleared(r, c+i) ) { clearSpace(r, c+i); cleared.add( new GridSpace(r, c+i) ); } } } } // if ( colorsMatch(match, first) ) } // column for loop } // row for loop return cleared; } // test components because we use alpha as a tag for removal private boolean colorsMatch(color c, color m) { return red(m) == red(c) && green(m) == green(c) && blue(m) == blue(c); } private void clearSpace(int r, int c) { color grid = cg.get(r, c); cg.set(r, c, color(red(grid), green(grid), blue(grid), 0)); } private boolean isCleared(int r, int c) { return isCleared(cg.get(r,c)); } private boolean isCleared(color c) { return alpha(c) == 0 || c == color(0); } // ********************************************************** // ** Refilling empty tiles // ********************************************************** // fill empty spaces by moving down tiles from above, if possible void dropTiles() { for(int r = cg.rows() - 1; r > 0; r--) { for(int c = 0; c < cg.cols(); c++) { if ( isCleared(r, c) ) { //println(r + " " + c + " is cleared."); // look above for an uncleared tile for(int i = r-1; i >= 0; i--) { if ( !isCleared(i, c) ) { color t = cg.get(i, c); cg.set(r, c, t); cg.set(i, c, color(0)); break; } } } } } } // returns the number of empty tiles in the grid int emptyTiles() { int[] grid = cg.getGrid(); int count = 0; for (int i = 0; i < grid.length; i++) { if ( isCleared(grid[i]) ) { count++; } } return count; } void queueTile(color c) { tileQueue = append(tileQueue, c); } // queue up tiles to appear from the top void queueTiles(color[] newTiles) { tileQueue = concat(tileQueue, newTiles); } // pulls tiles off the front of the tile queue and fills empty space void repop() { //println(tileQueue.length + " tiles in the tile queue."); int[] grid = cg.getGrid(); for (int i = 0; i < grid.length && tileQueue.length > 0; i++) { // if this grid position is empty, put a new tile if ( isCleared(grid[i]) ) { grid[i] = tileQueue[0]; tileQueue = subset(tileQueue, 1); } } } }