Game-Apps für Smartphones und Tablets |
|
Bern University oh Teacher Education |
|
![]() |
Beispiel im Online-Editor bearbeiten
App installieren auf Smartphone oder Tablet
Programmcode downloaden (Sokoban.zip)
Weitere Levels::
// Sokoban.java package app.sokoban; import ch.aplu.android.*; import ch.aplu.android.Location.CompassDirection; public class Sokoban extends GameGrid implements GGTouchListener { private final static SokobanGrid grid = new SokobanGrid(0); // 0, 1, or 2 private final static int nbHorzCells = grid.getNbHorzCells(); private final static int nbVertCells = grid.getNbVertCells(); private final int borderColor = RED; private SokobanStone[] stones = new SokobanStone[grid.getNbStones()]; private SokobanTarget[] targets = new SokobanTarget[grid.getNbStones()]; private SokobanActor sok; private boolean isFinished = false; public Sokoban() { super(nbHorzCells, nbVertCells, cellZoom(20), LTGRAY); setScreenOrientation(LANDSCAPE); } public void main() { initializeBord(); addTouchListener(this, GGTouch.press); showToast("Click next to Sokoban to move it into the desired direction."); } private void initializeBord() { GGBackground bg = getBg(); bg.clear(WHITE); bg.setPaintColor(DKGRAY); int stoneIndex = 0; int targetIndex = 0; for (int y = 0; y < nbVertCells; y++) { for (int x = 0; x < nbHorzCells; x++) { Location location = new Location(x, y); switch (grid.getCellTypeAt(location)) { case SOKOBAN: sok = new SokobanActor(); addActorNoRefresh(sok, location); break; case STONE: stones[stoneIndex] = new SokobanStone(); addActorNoRefresh(stones[stoneIndex], location); stoneIndex++; break; case TARGET_POSITION: targets[targetIndex] = new SokobanTarget(); addActorNoRefresh(targets[targetIndex], location); targetIndex++; break; case EMPTY_OUTSIDE: bg.fillCell(location, LTGRAY); break; case BORDER: bg.fillCell(location, borderColor); break; case EMPTY_INSIDE: // leave it white break; } } } setPaintOrder(SokobanTarget.class); refresh(); } private boolean canMove(Location nextLocation) { if (isBorder(nextLocation)) return false; else // Test if there is a stone { SokobanStone stone = getStoneAt(nextLocation); if (stone != null) { // Try to move the stone stone.setDirection(sok.getDirection()); if (moveStone(stone)) return true; else return false; } } return true; } private boolean moveStone(SokobanStone stone) { Location next = stone.getNextMoveLocation(); if (isBorder(next)) return false; // Test if there is another stone SokobanStone neighbourStone = getStoneAt(next); if (neighbourStone != null) return false; // Move the stone stone.setLocation(next); stone.updateSprite(); return true; } private boolean isBorder(Location loc) { int c = getBg().getColor(loc); return c == borderColor; } private SokobanStone getStoneAt(Location loc) { return (SokobanStone) getOneActorAt(loc, SokobanStone.class); } @Override public boolean touchEvent(GGTouch touch) { if (isFinished) return true; CompassDirection dir = sok.getLocation().get4CompassDirectionTo(toLocation(touch.getX(), touch.getY())); Location next = sok.getLocation().getNeighbourLocation(dir); sok.setDirection(dir); if (canMove(next)) { sok.setLocation(next); } refresh(); return true; } } // --------- SokobanActors------------- class SokobanActor extends Actor { public SokobanActor() { super(true, "sokoban"); // Rotatable } } class SokobanTarget extends Actor { public SokobanTarget() { super("target"); } } class SokobanStone extends Actor { public SokobanStone() { super("sokobanstone", 2); } /** * Changes appearance, if located at a target location. */ public void updateSprite() { if (gameGrid.getOneActorAt(getLocation(), SokobanTarget.class) != null) show(1); else show(0); } } // ------- class SokobanGrid ------------ class SokobanGrid { private final static int nbHorzCells = 19; private final static int nbVertCells = 11; private CellType[][] a = new CellType[nbHorzCells][nbVertCells]; private int nbStones = 0; private final static String soko_0 = " xxxxx " + // 0 (19) " x...x " + // 1 " x*..x " + // 2 " xxx..*xx " + // 3 " x..*.*.x " + // 4 "xxx.x.xx.x xxxxxx" + // 5 "x...x.xx.xxxxx..oox" + // 6 "x.*..*..........oox" + // 7 "xxxxx.xxx.xAxx..oox" + // 8 " x.....xxxxxxxxx" + // 9 " xxxxxxx "; // 10 private final static int nbHorzCells_0 = 19; private final static int nbVertCells_0 = 11; private final static String soko_1 = "xxxxxxxxxxxx " + // 0 (14) "xoo..x.....xxx" + // 1 "xoo..x.*..*..x" + // 2 "xoo..x*xxxx..x" + // 3 "xoo....A.xx..x" + // 4 "xoo..x.x..*.xx" + // 5 "xxxxxx.xx*.*.x" + // 6 " x.*..*.*.*.x" + // 7 " x....x.....x" + // 8 " xxxxxxxxxxxx"; // 9 private final static int nbHorzCells_1 = 14; private final static int nbVertCells_1 = 10; private final static String soko_2 = " xxxxxxxx " + // 0 (17) " x.....Ax " + // 1 " x.*x*.xx " + // 2 " x.*..*x " + // 3 " xx*.*.x " + // 4 "xxxxxxxxx.*.x.xxx" + // 5 "xoooo..xx.*..*..x" + // 6 "xxooo....*..*...x" + // 7 "xoooo..xxxxxxxxxx" + // 8 "xxxxxxxx "; // 9 private final static int nbHorzCells_2 = 17; private final static int nbVertCells_2 = 10; private final static String[] sokoModel = { soko_0, soko_1, soko_2 }; private final static int[] nbHorzCellsModel = { nbHorzCells_0, nbHorzCells_1, nbHorzCells_2 }; private final static int[] nbVertCellsModel = { nbVertCells_0, nbVertCells_1, nbVertCells_2 }; private int model; public SokobanGrid(int model) { this.model = model; // Copy structure into integer array for (int k = 0; k < nbVertCellsModel[model]; k++) { for (int i = 0; i < nbHorzCellsModel[model]; i++) { switch (sokoModel[model] .charAt(nbHorzCellsModel[model] * k + i)) { case ' ': a[i][k] = CellType.EMPTY_OUTSIDE; break; case '.': a[i][k] = CellType.EMPTY_INSIDE; break; case 'x': a[i][k] = CellType.BORDER; break; case '*': a[i][k] = CellType.STONE; nbStones++; break; case 'o': a[i][k] = CellType.TARGET_POSITION; break; case 'A': a[i][k] = CellType.SOKOBAN; break; } } } } public int getNbHorzCells() { return nbHorzCellsModel[model]; } public int getNbVertCells() { return nbVertCellsModel[model]; } public int getNbStones() { return nbStones; } public CellType getCellTypeAt(Location location) { return a[location.x][location.y]; } } // ------ class CellType ------- enum CellType { EMPTY_OUTSIDE, EMPTY_INSIDE, BORDER, STONE, TARGET_POSITION, SOKOBAN; } |