public class GameGrid extends JewelPuzzleGridCaller {
private JewelCell[][] jewelGrid;
private Coord selected;
private int width;
private int height;
private ArrayList<Coord> aChangedCells;
private ArrayList<Coord> 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<Coord>();
aToBeDestroyedCells = new ArrayList<Coord>();
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 <b>true</b> if there is at least one match, <b>false</b> 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<Coord> VLine = new ArrayList<Coord>();
ArrayList<Coord> HLine = new ArrayList<Coord>();
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<Coord> list = new ArrayList<Coord>();
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 <b>true</b> if pulled at least one gem, <b>false</b> if all lines were filled and no one was pulled.
*/
public boolean checkCellsAndPullDown(){
ArrayList<MoveCoord> list = new ArrayList<MoveCoord>();
for (int x = 0; x < width; x++) {
list.addAll(cellPullDown(x));
}
if (list.size() > 0) callExecutePullDown(list);
return list.size() > 0;
}
private ArrayList<MoveCoord> cellPullDown(int x){
ArrayList<MoveCoord> list = new ArrayList<MoveCoord>();
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;
}
}