Die Sokoban-Spielfigur Es ist eine einfache Sokoban-Impementierung mit drei Levels, die bei der Erzeugung des SokobanGrids festgelegt werden.
|
![]() |
Programmcode:
// Sokoban.java import ch.aplu.jgamegrid.*; import java.awt.event.KeyEvent; import java.awt.*; public class Sokoban extends GameGrid implements GGKeyListener { private class SokobanActor extends Actor { public SokobanActor() { super(true, "sprites/sokoban.gif"); // Rotatable } } private class SokobanTarget extends Actor { public SokobanTarget() { super("sprites/target.gif"); } } private class SokobanStone extends Actor { public SokobanStone() { super("sprites/stone.gif", 2); // Two sprites } } // ------------- End of inner classes ------ private final static SokobanGrid grid = new SokobanGrid(0); private final static int nbHorzCells = grid.getNbHorzCells(); private final static int nbVertCells = grid.getNbVertCells(); private final Color borderColor = new Color(130, 10, 50); 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, 30, false); setTitle("Sokoban"); GGBackground bg = getBg(); drawBoard(bg); drawActors(); addKeyListener(this); show(); // Check if finished int nbTarget = 0; while (nbTarget < grid.getNbStones()) { nbTarget = 0; for (int i = 0; i < grid.getNbStones(); i++) { if (stones[i].isVisible(1)) nbTarget++; } setTitle("# Stones at Target: " + nbTarget); delay(500); } setTitle("Game over. Well done!"); isFinished = true; playSound(this, GGSound.NOTIFY); } private void drawActors() { 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); int a = grid.getCell(location); if (a == 5) // Sokoban actor { sok = new SokobanActor(); addActor(sok, location); } if (a == 3) // Stones { stones[stoneIndex] = new SokobanStone(); addActor(stones[stoneIndex], location); stoneIndex++; } if (a == 4) // Targets { targets[targetIndex] = new SokobanTarget(); addActor(targets[targetIndex], location); targetIndex++; } } } setPaintOrder(SokobanTarget.class); } private void drawBoard(GGBackground bg) { bg.clear(new Color(230, 230, 230)); bg.setPaintColor(Color.darkGray); for (int y = 0; y < nbVertCells; y++) { for (int x = 0; x < nbHorzCells; x++) { Location location = new Location(x, y); int a = grid.getCell(location); if (a == 1 || a == 3 || a == 4 || a == 5) { bg.fillCell(location, Color.lightGray); Point center = toPoint(location); bg.drawLine(new Point(center.x - 15, center.y - 15), new Point(center.x + 15, center.y + 15)); bg.drawLine(new Point(center.x - 15, center.y + 15), new Point(center.x + 15, center.y - 15)); } if (a == 2) // Border bg.fillCell(location, borderColor); } } } public boolean keyPressed(KeyEvent evt) { if (isFinished) return true; Location next = null; switch (evt.getKeyCode()) { case KeyEvent.VK_LEFT: next = sok.getLocation().getNeighbourLocation(Location.WEST); sok.setDirection(Location.WEST); break; case KeyEvent.VK_UP: next = sok.getLocation().getNeighbourLocation(Location.NORTH); sok.setDirection(Location.NORTH); break; case KeyEvent.VK_RIGHT: next = sok.getLocation().getNeighbourLocation(Location.EAST); sok.setDirection(Location.EAST); break; case KeyEvent.VK_DOWN: next = sok.getLocation().getNeighbourLocation(Location.SOUTH); sok.setDirection(Location.SOUTH); break; } if (next != null && canMove(next)) { sok.setLocation(next); } refresh(); return true; } public boolean keyReleased(KeyEvent evt) { return true; } private boolean canMove(Location location) { // Test if try to move into border Color c = getBg().getColor(location); if (c.equals(borderColor)) return false; else // Test if there is a stone { SokobanStone stone = (SokobanStone)getOneActorAt(location, SokobanStone.class); 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(); // Test if try to move into border Color c = getBg().getColor(next); if (c.equals(borderColor)) return false; // Test if there is another stone SokobanStone neighbourStone = (SokobanStone)getOneActorAt(next, SokobanStone.class); if (neighbourStone != null) return false; // Move the stone stone.setLocation(next); // Check if we are at a target if (getOneActorAt(next, SokobanTarget.class) != null) stone.setVisible(1, true); else stone.setVisible(0, true); return true; } public static void main(String[] args) { new Sokoban(); } } class SokobanGr { private final static int nbHorzCells = 19; private final static int nbVertCells = 11; private static int[][] a = new int[nbHorzCells][nbVertCells]; private static 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 static 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] = 0; // Empty outside break; case '.': a[i][k] = 1; // Empty inside break; case 'x': a[i][k] = 2; // Border break; case '*': a[i][k] = 3; // Stones nbStones++; break; case 'o': a[i][k] = 4; // Target positions break; case 'A': a[i][k] = 5; // Sokoban actor break; } } } } public static int getNbHorzCells() { return nbHorzCellsModel[model]; } public static int getNbVertCells() { return nbVertCellsModel[model]; } public static int getNbStones() { return nbStones; } public static int getCell(Location location) { return a[location.x][location.y]; } } |