📄 board.java
字号:
/* * * Copyright (c) 2007, Sun Microsystems, Inc. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package example.pushpuzzle;import javax.microedition.lcdui.*;/** * The class Board knows how the pieces move, handles undo, and * handles reading of screens. */public class Board { // 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 private int level; private byte[] array; private byte[] pathmap; // used for runTo to find shortest path private int width; private int height; private int pusher; // position of the pusher at index into array private int packets = 0; // total number of packets private int stored = 0; // number of packets in Stores private byte[] moves; // recorded moves private int nmoves; // number of moves executed private int npushes; // number of pushes executed /** * 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]; level = 0; 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 * @return the direction actually moved, -1 if not moved */ public int move(int move) { int obj = pusher + indexOffset(move); // Handle the simple cases if ((array[obj] & WALL) != 0) { return -1; } int m = movePacket(obj, move); if (m < 0) { return -1; // If can't move packet, done! } pusher = obj; // move the pusher to the new spot saveMove(m); return 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 * @return the move undone; if none -1 is returned; * See LEFT, RIGHT, UP, DOWN, and MOVEPACKET */ public int undoMove() { if (nmoves <= 0) { return -1; } 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); // move packet } pusher = back; return move; } /** * Determine if the screen has been solved. */ public boolean solved() { return packets == stored; } /** * Move the player to the position (x,y), if possible. Return * the direction it moved if successful, otherwise -1. * The position (x,y) must be empty. * @param x window coordinate * @param y window coordinate * @return the direction that it moved, -1 is not moved; * See LEFT, RIGHT, UP, DOWN, MOVEPACKET */ public int runTo(int x, int y, int max) { int target = index(x, y); if ((target < 0) || (target >= array.length)) { return -1; } if (target == pusher) { return -1; // already there } /* Fill the path map */ if ((pathmap == null) || (pathmap.length != array.length)) { pathmap = new byte[array.length]; } // Fill with unset value. for (int i = 0; i < pathmap.length; i++) pathmap[i] = 127; // flood fill search to find a shortest path to the push point. findTarget(target, (byte)0); /* * if we didn't make it back to the players position, * there is no valid path to that place. */ if (pathmap[pusher] == 127) { return -1; } else { // We made it back, so let's walk the path we just built up // Save the final move to return int pathlen = pathmap[pusher]; int pathmin = pathlen - max; int dir = -1; for (pathlen--; pathlen >= pathmin; pathlen--) { if (pathmap[pusher - 1] == pathlen) { dir = LEFT; saveMove(dir); pusher--; } else if (pathmap[pusher + 1] == pathlen) { dir = RIGHT; saveMove(dir); pusher++; } else if (pathmap[pusher - width] == pathlen) { dir = UP; saveMove(dir); pusher -= width; } else if (pathmap[pusher + width] == pathlen) { dir = DOWN; saveMove(dir); pusher += width; } else { /* * if we get here, something is SERIOUSLY wrong, * so we should abort */ throw new RuntimeException("runTo abort"); } } return dir; } } /** * Find the shortest path to the pusher via a fill search algorithm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -