Created
October 25, 2013 17:08
-
-
Save xoppa/7158179 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Grid<T extends Grid.GridCell> { | |
public interface GridCell { | |
int getX(); | |
int getY(); | |
void setLocation(int x, int y); | |
} | |
public interface CellProvider<T extends GridCell> { | |
T obtainCell(); | |
void releaseCell(T b); | |
} | |
private final Array<T> cells; | |
private final CellProvider<T> provider; | |
private int width, height; | |
protected static int reasonCounter = 0; | |
public final static int ReasonFill = reasonCounter++; | |
public Grid(final CellProvider<T> provider) { | |
this.provider = provider; | |
this.cells = new Array<T>(); | |
} | |
public T obtain() { | |
return (provider == null) ? null : provider.obtainCell(); | |
} | |
public void release(final T cell) { | |
if (provider != null && cell != null) | |
provider.releaseCell(cell); | |
} | |
public int getWidth() { | |
return width; | |
} | |
public int getHeight() { | |
return height; | |
} | |
public void setSize(int width, int height) { | |
this.width = width; | |
this.height = height; | |
final int s = width * height; | |
while (s < cells.size) { | |
final T old = cells.pop(); | |
if (old != null) | |
release(old); | |
} | |
if (s > cells.size) { | |
cells.ensureCapacity(s); | |
while (s > cells.size) | |
cells.add(null); | |
} | |
} | |
/** Releases all cells (if not null) and sets them to null */ | |
public void clear() { | |
T cell; | |
for (int i = cells.size - 1; i >= 0; i--) { | |
if ((cell = cells.get(i)) != null) { | |
release(cell); | |
cells.set(i, null); | |
} | |
} | |
} | |
/** @return the cell at the specified location or null if the location is out of range */ | |
public T get(int x, int y) { | |
return (x < 0 || x >= width || y < 0 || y >= height) ? null : cells.get(y * width + x); | |
} | |
/** Releases the call at the specified location (if any) and sets it to null */ | |
public void remove(int x, int y, boolean release) { | |
final int idx = y * width + x; | |
T cell = cells.get(idx); | |
if (cell != null) { | |
if (release) | |
release(cell); | |
cells.set(idx, null); | |
} | |
} | |
public void remove(T cell, boolean release) { | |
if (cell == null) | |
return; | |
int idx = cells.indexOf(cell, true); | |
if (idx >= 0) | |
cells.set(idx, null); | |
if (release) | |
release(cell); | |
} | |
public void removeAll(Iterable<T> cells, boolean release) { | |
for (T cell : cells) | |
remove(cell, release); | |
} | |
/** Replaces the cell at the specified location with a new cell, releasing the old one (if any) */ | |
public void set(int x, int y, int reason) { | |
set(x, y, obtain(), reason); | |
} | |
/** Replaces the cell at the specified location with the specified cell, releasing the old one (if any) */ | |
public void set(int x, int y, T cell, int reason) { | |
if (x < 0 || x >= width || y < 0 || y >= height) | |
return; | |
remove(x, y, true); | |
final int idx = y * width + x; | |
cells.set(idx, cell); | |
cell.setLocation(x, y); | |
} | |
/** Fills all null cells by obtaining a new cell */ | |
public void fill() { | |
for (int i = cells.size - 1; i >= 0; i--) { | |
if (cells.get(i) == null) | |
set(i % width, i / width, ReasonFill); | |
} | |
} | |
public void swap(int x1, int y1, int x2, int y2) { | |
if (x1 < 0 || x1 >= width || y1 < 0 || y1 >= height || x2 < 0 || x2 >= width || y2 < 0 || y2 >= height) | |
return; | |
final int i1 = y1 * width + x1; | |
final int i2 = y2 * width + x2; | |
T c1 = cells.get(i1); | |
T c2 = cells.get(i2); | |
cells.set(i1, c2); | |
cells.set(i2, c1); | |
if (c1 != null) | |
c1.setLocation(x2, y2); | |
if (c2 != null) | |
c2.setLocation(x1, y1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment