package aima.core.environment.cellworld; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; /** * Artificial Intelligence A Modern Approach (3rd Edition): page 645.<br> * <br> * * A representation for the environment depicted in figure 17.1.<br> * <br> * <b>Note:<b> the x and y coordinates are always positive integers starting at * 1.<br> * <b>Note:<b> If looking at a rectangle - the coordinate (x=1, y=1) will be the * bottom left hand corner.<br> * * * @param <C> * the type of content for the Cells in the world. * * @author Ciaran O'Reilly * @author Ravi Mohan */ public class CellWorld<C> { private Set<Cell<C>> cells = new LinkedHashSet<Cell<C>>(); private Map<Integer, Map<Integer, Cell<C>>> cellLookup = new HashMap<Integer, Map<Integer, Cell<C>>>(); /** * Construct a Cell World with size xDimension * y Dimension cells, all with * their values set to a default content value. * * @param xDimension * the size of the x dimension. * @param yDimension * the size of the y dimension. * * @param defaultCellContent * the default content to assign to each cell created. */ public CellWorld(int xDimension, int yDimension, C defaultCellContent) { for (int x = 1; x <= xDimension; x++) { Map<Integer, Cell<C>> xCol = new HashMap<Integer, Cell<C>>(); for (int y = 1; y <= yDimension; y++) { Cell<C> c = new Cell<C>(x, y, defaultCellContent); cells.add(c); xCol.put(y, c); } cellLookup.put(x, xCol); } } /** * * @return all the cells in this world. */ public Set<Cell<C>> getCells() { return cells; } /** * Determine what cell would be moved into if the specified action is * performed in the specified cell. Normally, this will be the cell adjacent * in the appropriate direction. However, if there is no cell in the * adjacent direction of the action then the outcome of the action is to * stay in the same cell as the action was performed in. * * @param s * the cell location from which the action is to be performed. * @param a * the action to perform (Up, Down, Left, or Right). * @return the Cell an agent would end up in if they performed the specified * action from the specified cell location. */ public Cell<C> result(Cell<C> s, CellWorldAction a) { Cell<C> sDelta = getCellAt(a.getXResult(s.getX()), a.getYResult(s .getY())); if (null == sDelta) { // Default to no effect // (i.e. bumps back in place as no adjoining cell). sDelta = s; } return sDelta; } /** * Remove the cell at the specified location from this Cell World. This * allows you to introduce barriers into different location. * * @param x * the x dimension of the cell to be removed. * @param y * the y dimension of the cell to be removed. */ public void removeCell(int x, int y) { Map<Integer, Cell<C>> xCol = cellLookup.get(x); if (null != xCol) { cells.remove(xCol.remove(y)); } } /** * Get the cell at the specified x and y locations. * * @param x * the x dimension of the cell to be retrieved. * @param y * the y dimension of the cell to be retrieved. * @return the cell at the specified x,y location, null if no cell exists at * this location. */ public Cell<C> getCellAt(int x, int y) { Cell<C> c = null; Map<Integer, Cell<C>> xCol = cellLookup.get(x); if (null != xCol) { c = xCol.get(y); } return c; } }