public class GameGrid extends JewelPuzzleGridCaller { private JewelCell[][] jewelGrid; private Coord selected; private int width; private int height; private ArrayList aChangedCells; private ArrayList aToBeDestroyedCells; private int chainCount = 0; private JewelGameManager myManager; public GameGrid(int width,int height, JewelGameManager myManager) { jewelGrid = new JewelCell[width][height]; this.myManager = myManager; this.width = width; this.height = height; aChangedCells = new ArrayList(); aToBeDestroyedCells = new ArrayList(); selected = new Coord(-1, -1); } public void initialize() { for (int x = 0; x < this.width; x++) { for (int y = 0; y < this.height; y++) { jewelGrid[x][y] = new JewelCell(null); } } checkCellsAndPullDown(); //updateValidMoves(); } public int getWidth() { return width; } public int getHeight() { return height; } public boolean hasSelected(){ return (this.selected != null && this.selected.getX() > -1 && this.selected.getY() > -1); } public Coord getSelected() { return selected; } public void select(int x, int y){ this.selected.setCoords(x, y); callShowSelectedMarker(x, y, true); } public void deSelect(){ this.selected.setCoords(-1, -1); callShowSelectedMarker(0, 0, false); } public JewelCell getCell(int x, int y){ return jewelGrid[x][y]; } public JewelCell getCell(Coord coord){ return jewelGrid[coord.getX()][coord.getY()]; } public int getChainCount() { return chainCount; } public void resetChainCount() { this.chainCount = 0; } private void addCellToBeChecked(int x, int y){ addCellToBeChecked(new Coord(x, y)); } private void addCellToBeChecked(Coord coord){ aChangedCells.add(coord); } private boolean checkChangedCellsForMatches(){ boolean result = false; if (aChangedCells.size() > 0){ for (Coord coord : aChangedCells) { if (checkCellForMatches(coord)){ result = true; } } } return result; } /** * Check all cells from the grid for matches. * @return true if there is at least one match, false otherwise. */ public boolean checkGridForMatches(){ for (int x = 0; x < width; x++) { for (int y = 2; y < height; y++) { checkCellForMatches(new Coord(x, y)); } } return clearMarkedCells(); } private boolean checkCellForMatches(Coord pCoord){ ArrayList VLine = new ArrayList(); ArrayList HLine = new ArrayList(); JewelType type; for (Coord coord : aToBeDestroyedCells) { // if the cell is already marked for destruction skip the check. It is doomed. if (coord.match(pCoord)) return false; } boolean result = false; final int x = pCoord.getX(); final int y = pCoord.getY(); type = getCell(x, y).getType(); // @Anila // this 'for' is because my gems can have more than one type of color // so I check every type // regular 1-color gems don't need the 'for' for (JewelColor color : type.getColors()) { HLine.clear(); VLine.clear(); for (int xt = x; xt >= 0 && JewelType.isMatch(getCell(xt, y).getType(), color); xt--) { HLine.add(new Coord(xt, y)); } for (int xt = x +1; xt < width && JewelType.isMatch(getCell(xt, y).getType(), color); xt++) { HLine.add(new Coord(xt, y)); } //yt = 2 to ignore the first 2 lines, they will be hidden unless the player has the proper ability for (int yt = y; yt >= 2 && JewelType.isMatch(getCell(x, yt).getType(), color); yt--) { VLine.add(new Coord(x, yt)); } for (int yt = y +1; yt < height && JewelType.isMatch(getCell(x, yt).getType(), color); yt++) { VLine.add(new Coord(x, yt)); } if (HLine.size() > 2){ aToBeDestroyedCells.addAll(HLine); result = true; } if (VLine.size() > 2){ aToBeDestroyedCells.addAll(VLine); result = true; } } return result; } /* private void updateValidMoves(){ }*/ public boolean clearMarkedCells(){ ArrayList list = new ArrayList(); if (aToBeDestroyedCells.size() > 0){ for (Coord coord : aToBeDestroyedCells) { if (!getCell(coord).isEmpty()){ for (JewelColor color : getCell(coord).getType().getColors()) { myManager.matchedPoints(color, 1, coord); } getCell(coord).setEmpty(); list.add(coord); } } callClearMatchedCells(list); aToBeDestroyedCells.clear(); chainCount++; return true; } else { return false; } } public void swapCell(int x1, int y1, int x2, int y2){ deSelect(); JewelCell cell1 = jewelGrid[x1][y1]; JewelCell cell2 = jewelGrid[x2][y2]; jewelGrid[x1][y1] = cell2; jewelGrid[x2][y2] = cell1; aChangedCells.clear(); addCellToBeChecked(x1, y1); addCellToBeChecked(x2, y2); if (checkChangedCellsForMatches()){ callSwapJewels(x1, y1, x2, y2); } else { jewelGrid[x1][y1] = cell1; jewelGrid[x2][y2] = cell2; callSwapJewelsFailed(x1, y1, x2, y2); } } /** * Pull all gems down from bottom to top creating new gems as needed * @return true if pulled at least one gem, false if all lines were filled and no one was pulled. */ public boolean checkCellsAndPullDown(){ ArrayList list = new ArrayList(); for (int x = 0; x < width; x++) { list.addAll(cellPullDown(x)); } if (list.size() > 0) callExecutePullDown(list); return list.size() > 0; } private ArrayList cellPullDown(int x){ ArrayList list = new ArrayList(); final int BOTTOM = height -1; JewelCell upcell; for (int y = BOTTOM; y >= 0; y--) { JewelCell cell = getCell(x, y); if (cell.isEmpty()){ Coord toCoord = new Coord(x, y); Coord fromCoord = new Coord(x, -1); boolean foundCell = false; for (int curY = y -1; curY >= 0 && !foundCell; curY--){ if (curY >= 0 && !(upcell = getCell(x, curY)).isEmpty()){ cell.setType(upcell.getType()); upcell.setEmpty(); fromCoord.setCoords(x, curY); foundCell = true; } } if (foundCell){ list.add(new MoveCoord(fromCoord, toCoord)); } else { list.add(new MoveCoord(fromCoord, toCoord, cell.newType())); } } } return list; } }