Skip to content

Instantly share code, notes, and snippets.

@xoppa
Created October 25, 2013 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xoppa/7158179 to your computer and use it in GitHub Desktop.
Save xoppa/7158179 to your computer and use it in GitHub Desktop.
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