📄 board.java
字号:
/* * @(#)Board.java 1.4 01/04/04 * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved. */package examples.sokoban;import java.io.IOException;/** * Board knows how to move the pusher and how the pusher moves * the pieces. It also keeps track of the number of moves * and pushes and the level. */public class Board { /* * Directly accessible fields of the game board; * do not set outside this class. */ int width; // Width of the board int height; // Height of the board int nmoves; // number of moves executed int npushes; // number of pushes executed private byte[] array; // width * height array of game state private int pusher; // position of the pusher at index into array private int packets; // total number of packets private int stored; // number of packets in Stores private byte[] moves; // recorded moves for undo // Move directions public static final int LEFT = 0; public static final int RIGHT = 3; public static final int UP = 1; public static final int DOWN = 2; public static final int MOVEPACKET = 4; // Bit definitions for pieces of each board position public static final byte GROUND = 0; // If nothing there public static final byte STORE = 1; // If it is a storage place public static final byte PACKET = 2; // If it has a packet public static final byte WALL = 4; // If it is a wall public static final byte PUSHER = 8; // If the pusher is there /** * Creates new Board initialized to a simple puzzle. */ public Board() { moves = new byte[200]; screen0(); } /* * Create the hard coded simple game board. */ public void screen0() { width = 9; height = 7; array = new byte[width*height]; nmoves = 0; npushes = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { byte t = (x == 0 || y == 0 || x == width-1 || y == height-1) ? WALL : GROUND; set(x, y, t); } } packets = 2; stored = 0; set(2, 2, PACKET); set(4, 4, PACKET); set(4, 2, STORE); set(6, 4, STORE); pusher = index(1, 1); } /** * Move the pusher in the direction indicated. * If there is a wall, don't move. * if there is a packet in that direction, try to move it. * @param move the direction; one of LEFT, RIGHT, UP, DOWN */ public void move(int move) { int p = pusher + indexOffset(move); // Handle the simple cases if ((array[p] & WALL) != 0) return; int m = movePacket(p, move); if (m >= 0) { /* * Put the pusher in the new index * and save the move in case of undo. */ pusher = p; saveMove(m); } } /** * Move the packet in the direction indicated relative to * the pusher. If it fits into a store position remember. * @return -1 if can't be moved or the updated move * including the packet flag if there was a packet to move. */ private int movePacket(int index, int move) { if ((array[index] & PACKET) == 0) return move; // no packet to move int dest = index + indexOffset(move); if (array[dest] > STORE) return -1; // can't move packet into next spot. // Remove packet from current location array[index] &= ~PACKET; if ((array[index] & STORE) != 0) stored--; // Insert packet into new location array[dest] |= PACKET; if ((array[dest] & STORE) != 0) stored++; npushes++; // count pushes done return move + MOVEPACKET; } /* * Save a move, extending the array if necessary. */ private void saveMove(int move) { if (nmoves >= moves.length) { byte[] n = new byte[moves.length+50]; System.arraycopy(moves, 0, n, 0, moves.length); moves = n; } moves[nmoves++] = (byte)move; } /* * Undo the most recent move */ public void undoMove() { if (nmoves <= 0) return; int move = moves[--nmoves]; int rev = (move & 3) ^ 3; // reverse the direction int back = pusher + indexOffset(rev); if ((move & MOVEPACKET) != 0) { npushes--; // "unpush" movePacket(pusher + indexOffset(move), rev); } pusher = back; } /** * Determine if the screen has been solved. */ public boolean solved() { return packets == stored; } /* * Return the pieces at the location. * @param x location in the board. * @param y location in the board. * @return flags indicating what pieces are in this location. * Bit flags; combinations of WALL, PUSHER, STORE, PACKET. */ public byte get(int x, int y) { int offset = index(x, y); if (offset == pusher) return (byte)(array[offset] | PUSHER); else return array[offset]; } private void set(int x, int y, byte value) { array[index(x, y)] = value; } private int index(int x, int y) { if (x < 0 || x >= width || y < 0 || y >= height) return -1; return y * width + x; } /* * Compute the offset in the array of the cell relative * to the current pusher location in the direction of the move. * Note: the walls around the edge always make a +/- guard band. * Also, the order of evaluation should never try to get to +/- 2. */ private int indexOffset(int move) { switch (move & 3) { case LEFT: return -1; case RIGHT: return +1; case UP: return -width; case DOWN: return +width; } return 0; } /** * Read a board from a stream. * Read it into a fixed size array and then shrink to fit. */ public void read(java.io.InputStream is, int lev) throws IOException { final int W = 20; final int H = 20; byte[] b = new byte[W*H]; int c, w = 0; int x = 0, y = 0, xn = 0, yn = 0; packets = 0; stored = 0; nmoves = 0; npushes = 0; while ((c = is.read()) != -1) { switch (c) { case '\n': if (x > w) { w = x; } y++; x = 0; break; case '$': b[y*W + x++] = PACKET; packets++; break; case '#': b[y*W + x++] = WALL; break; case ' ': b[y*W + x++] = GROUND; break; case '.': b[y*W+ x++] = STORE; break; case '+': // player and store in same place b[y*W + x++] = STORE; case '@': xn = x; yn = y; x++; break; } } /* * Copy the board to an array sized to the \ * width and height of the board. */ width = w; height = y; array = new byte[width * height]; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { array[y * width + x] = b[y * W + x]; } } pusher = index(xn, yn); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -