ArrayIndexOutOfBoundsException:0使用Vector

时间:2014-08-29 16:35:26

标签: java vector indexoutofboundsexception

我收到错误:

java.lang.ArrayIndexOutOfBoundsException: 0
    at tesseract.BlockMaze.generate(BlockMaze.java:128)
    at tesseract.MazeMap.<init>(MazeMap.java:17)
    at tesseract.main.init(main.java:29)
    at sun.applet.AppletPanel.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

以下是部分:

第29行:

    map = new MazeMap(mwidth, mheight);

MazeMap第17行:

    generate(false);

BlockMaze第128行:

    maze[startX = 0][startY = rint(mzHyt - 2) + 1] = FLOOR;

我正在使用Vector类型,我想知道是否可能是我遇到的问题。 Vector是不推荐使用的类型,是否有替代品。还有一个替代方案,因为我尝试使用ArrayList,但我不完全确定它是否会做同样的事情。

这是BlockMaze:

package tesseract;

import java.awt.Color;
import java.util.Vector;

public class BlockMaze extends Maze{

private static final long serialVersionUID = -4392133669361871887L;
public static final byte WALL = 0, FLOOR = 1;
private Vector  pending;     // list of available Sqr objects
private int     strt =  70;  // prob of exploring from same sqr
private int     sdir =  60;  // prob of exploring in same dir (if possible)
private int     thru =  90;  // prob of blocking thru loops
private int     side =  60;  // prob of blocking wide areas
private int     diag = 100;  // prob of blocking diag connections
private int     dens =  15;  // prob of leaving areas unexplored

public BlockMaze () {
    setBackground(Color.black);
}

protected byte initSq () { return (byte) (WALL | DIRTY); }

protected void drawSquare (int xx, int yy) {
    offscr.setColor(maze[xx][yy] == WALL ? Color.gray : Color.white);
    offscr.fillRect(leftOffset + (xx * sqWid), topOffset + (yy * sqHyt), sqWid, sqHyt);
}

public boolean isOpen (int x, int y) {
    return inBounds(x, y)  &&  sqr(x, y) == FLOOR;
}

private boolean isOpen (int x, int y, int allowProb) {
    return prob(allowProb)  &&  isOpen(x, y);
}

private boolean blocked (int x, int y) {
    return inBounds(x, y)  &&  sqr(x, y) == WALL;
}

private boolean noDiag (int x, int y, int dx, int dy) {
    return blocked(x + dx, y)  &&  blocked(x, y + dy)  &&  isOpen(x + dx, y + dy, diag);
}

private boolean tryDir (int x, int y, int dir) {
    // Step #7 - check if the adjacent square in direction 'dir' should be
added to the maze
    // Currently I disallow any move that would create a loop or a path width
    // greater than one square.  However, I believe I can get more interesting
    // mazes if I use probability to selectively allow this.
    switch (dir) {
        case TOP:
            y--;
            if (isOpen(x, y - 1, thru) ||
                    isOpen(x - 1, y, side) || isOpen(x + 1, y, side) ||
                    noDiag(x, y, -1, -1) || noDiag(x, y, 1, -1))
                return false;
            break;
        case BOTTOM:
            y++;
            if (isOpen(x, y + 1, thru) ||
                    isOpen(x - 1, y, side) || isOpen(x + 1, y, side) ||
                    noDiag(x, y, -1, 1) || noDiag(x, y, 1, 1))
                return false;
            break;
        case LEFT:
            x--;
            if (isOpen(x - 1, y, thru) ||
                    isOpen(x, y - 1, side) || isOpen(x, y + 1, side) ||
                    noDiag(x, y, -1, -1) || noDiag(x, y, -1, 1))
                return false;
            break;
        case RIGHT:
            x++;
            if (isOpen(x + 1, y, thru) ||
                    isOpen(x, y - 1, side) || isOpen(x, y + 1, side) ||
                    noDiag(x, y, 1, -1) || noDiag(x, y, 1, 1))
                return false;
            break;
    }
    if (finishX < 0  &&  x == mzWid - 1) {
        finishX = x;  finishY = y;  // found exit
    }
    else if (x <= 0  ||  x >= mzWid - 1  ||  y <= 0  ||  y >= mzHyt - 1)
        return false;  // square on border or out of bounds
    else {
        Sqr sq = new Sqr(x, y, dir, blocked(x, y-1), blocked(x, y+1),
                                    blocked(x-1, y), blocked(x+1, y));
        // if pruning density, replace last pending Sqr
        if (pending.size() > 10  &&  prob(dens))
            pending.setElementAt(sq, pending.size() - 1);
        else  // not pruning, add pending Sqr to list
            pending.addElement(sq);
    }
    maze[x][y] = FLOOR;
    dirtySquare(x, y);
    return true;
}

/* Here are the steps generate() uses to generate a maze:
 *  1.  Set all the squares in the maze grid to WALL.
 *  2.  Randomly select a non-corner square on the left edge of the maze,
 *      set the square to FLOOR. Create a Sqr object with the RIGHT direction
 *      unexplored and add it to the list of available squares.
 *  3.  If the list of available squares is empty, then you're done.
 *  4.  Select a square to explore from the list of available squares.
 *  5.  If less than two directions remain to be explored from the square,
 *      remove the square from the list of available squares. You remove
 *      the square from the list because no directions will be left to
 *      explore after you process the square.
 *  6.  Select a direction to explore from the square and mark the direction
 *      as explored.
 *  7.  Check to see if you should add the square in the selected direction
 *      to the maze grid. If the answer is ÔyesÕ, then add the square to the
 *      maze and to the list of available squares.
 *  8.  Goto step 3.
 */

public synchronized void generate (boolean displayConstruction) {
    int free, idx;

    // Step #1 - initialize the maze
    clearMaze();
    if (displayConstruction)
        showMaze(true);

    // Step #2 - select and set the starting square
    pending = new Vector();
    maze[startX = 0][startY = rint(mzHyt - 2) + 1] = FLOOR;
    dirtySquare(startX, startY);
    pending.addElement(new Sqr(startX, startY, RIGHT, false, false, false, true));

    // Step #3 - loop until list of squares is empty
    while (!pending.isEmpty()) {
        // Step #4 - select a square to explore
        // You can vary the "character" of the generated maze by adjusting how
frequently
        // the algorithm chooses to continue expanding from the current square vs. how
        // frequently it randomly picks another queue square.
        if (prob(strt))
            idx = pending.size() - 1;
        else
            idx = rint(pending.size());
        Sqr next = (Sqr) pending.elementAt(idx);
        // Step #5 - remove the square if this is the last side to explore
        // Also randomly remove squares to reduce maze density.
        if ((free = next.open()) <= 1  ||  (pending.size() > 10  &&  prob(dens)))
            pending.removeElementAt(idx);
        if (free > 0) {
            // Step #6a - select a direction to explore
            // You can also vary the character of the maze by altering the probability
that
            // Sqr.select() will be asked to try to continue to expand the next square
in the
            // same direction we entered the square being expanded.  This tends to
reduce
            // the zig-zag nature that results from straight random
selection of direction.
            if (tryDir(next.x, next.y, next.select(rint(free), prob(sdir))))
                if (displayConstruction)
                    showMaze(false);
        }
        // Step #8 - explore another square
    }
    if (!displayConstruction)
        repaint();
}

public synchronized boolean traverse (int sx, int sy, int fx, int fy, boolean
displaySearch) {
    if (!inBounds(sx, sy)  ||  !inBounds(fx, fy))
        return false;

    int         dir, xx = sx, yy = sy, count = 0;
    int         qhead, qtail, qsize = (mzWid + mzHyt - 1) * 2;
    short[][]   queue = new short[qsize][2];  // 0 = x, 1 = y
    byte[][]    graph = new byte[mzWid][mzHyt];
    boolean     solve = (xx == startX && yy == startY && fx == finishX && fy ==finishY);

    if (displaySearch) {
        resetPath();
        if (solve) {
            path[sx][sy] = LEFT;
            dirtySquare(sx, sy);
        }
        showMaze(false);
    }
    graph[xx][yy] = -1;
    queue[0][0] = (short)xx;  queue[0][1] = (short)yy;
    qtail = 0;  qhead = 1;

 TRAVERSE:
    for (;;) {
        if (qhead == qtail) {  // queue is empty: unsolvable maze
            resetPath();
            if (displayPath)
                repaint();
            return false;
        }
        xx = queue[qtail][0];  yy = queue[qtail][1];
        qtail = (qtail + 1) % qsize;
        int qstart = qhead;
        for (dir = TOP;  dir <= LEFT;  dir <<= 1) {
            int ndir = 0, nx = xx, ny = yy;
            switch (dir) {
                case TOP:     ny--;  ndir = BOTTOM;  break;
                case RIGHT:   nx++;  ndir = LEFT;    break;
                case BOTTOM:  ny++;  ndir = TOP;     break;
                case LEFT:    nx--;  ndir = RIGHT;   break;
            }
            if (inBounds(nx, ny)  &&  graph[nx][ny] == 0  &&  sqr(nx, ny) == FLOOR) {
                // extend the search path in direction <dir>
                graph[nx][ny] = (byte)ndir;  // point to previous square
                if (displaySearch) {
                    path[xx][yy] |= dir;
                    dirtySquare(xx, yy);
                    path[nx][ny] |= ndir;
                    dirtySquare(nx, ny);
                }
                if (nx == fx  &&  ny == fy)  // found solution
                    break TRAVERSE;
                queue[qhead][0] = (short)nx;  queue[qhead][1] = (short)ny;
                qhead = (qhead + 1) % qsize;
            }
        }
        if (displaySearch) {
            if (qhead == qstart) {  // dead end, backtrack
                while (path[xx][yy] == graph[xx][yy]) {
                    path[xx][yy] = 0;
                    dirtySquare(xx, yy);
                    switch (graph[xx][yy]) {
                        case TOP:     path[xx][--yy] &= (byte)~BOTTOM;  break;
                        case RIGHT:   path[++xx][yy] &= (byte)~LEFT;    break;
                        case BOTTOM:  path[xx][++yy] &= (byte)~TOP;     break;
                        case LEFT:    path[--xx][yy] &= (byte)~RIGHT;   break;
                    }
                    dirtySquare(xx, yy);
                }
            }
            showMaze(false);
        }
        else if ((++count & 0xFF) == 0)
            Thread.yield();
    }
    if (displaySearch) {
        if (solve) {
            path[xx][yy] |= RIGHT;
            dirtySquare(xx, yy);
        }
        showMaze(false);
    }

    // reconstruct path by following graph from finish to start
    resetPath();
    if (solve)
        path[fx][fy] = RIGHT;
    while ((dir = graph[fx][fy]) != -1) {
        path[fx][fy] |= (byte)dir;
        switch (dir) {
            case TOP:     path[fx][--fy] = BOTTOM;  break;
            case RIGHT:   path[++fx][fy] = LEFT;    break;
            case BOTTOM:  path[fx][++fy] = TOP;     break;
            case LEFT:    path[--fx][fy] = RIGHT;   break;
        }
    }
    if (solve)
        path[fx][fy] |= LEFT;
    if (displayPath)
        repaint();
    return true;
}
}  // public class BlockMaze



class Sqr {
private boolean t, b, l, r;  // top, bottom, left, right
private int     dir;         // direction square entered
int             x, y;        // coordinates of square

Sqr (int x, int y, int dir, boolean t, boolean b, boolean l, boolean r) {
    this.x = x;  this.y = y;
    this.dir = dir;
    this.t = t;  this.b = b;  this.l = l;  this.r = r;
}

// open() returns a count of the unexplored directions
int open () {
    return (t ? 1 : 0) + (b ? 1 : 0) + (r ? 1 : 0) + (l ? 1 : 0);
}

int select (int n, boolean sameDir) {
    // Step #6b - select a direction to explore and mark the direction as explored
    if (sameDir)  // try to expand in same direction the square was entered from
        switch (dir) {
            case Maze.TOP:    if (t) { t = false; return dir; }  break;
            case Maze.BOTTOM: if (b) { b = false; return dir; }  break;
            case Maze.LEFT:   if (l) { l = false; return dir; }  break;
            case Maze.RIGHT:  if (r) { r = false; return dir; }  break;
        }
    // return the 'n'th unexplored direction
    if      (t && --n < 0) { t = false; return Maze.TOP;    }
    else if (b && --n < 0) { b = false; return Maze.BOTTOM; }
    else if (r && --n < 0) { r = false; return Maze.RIGHT;  }
    else                   { l = false; return Maze.LEFT;   }
}
}  // class Sqr

这是阵列迷宫。

protected byte[][] maze, path;

这就是重新初始化迷宫的原因:

protected void showMaze (boolean allDirty) {
    if (allDirty  ||  offscreenImage == null)
        repaint();
    else
        repaint(leftOffset + minXdirty * sqWid, topOffset + minYdirty * sqHyt,
                sqWid * (maxXdirty - minXdirty + 1) + lineWid,
                sqHyt * (maxYdirty - minYdirty + 1) + lineHyt);
    try { wait(); } catch (InterruptedException e) {}
    long t = System.currentTimeMillis();
    if ((timer -= t - (1000L / maxFrameRate)) > 0)
        try { Thread.sleep(timer); } catch (InterruptedException e) {}
    timer = System.currentTimeMillis();
}

protected void clearMaze(){
    if(maze == null)
        maze = new byte[mzWid][mzHyt];
    byte sq = initSq();
    for(int xx = mzWid; --xx >= 0;)
        for(int yy = mzHyt; --yy >= 0;)
        maze[xx][yy] = sq;
    minXdirty = minYdirty = 0;
    maxXdirty = mzWid - 1;
    maxYdirty = mzHyt - 1;
    startX = finishX = -1;
    path = null;
}

我相信这就是我所寻找的:

public synchronized void setDimensions(int squaresWide, int squaresHigh){
    if(mzWid != squaresWide || mzHyt != squaresHigh){
        mzWid = Math.max(3,  squaresWide);  //min maze width is 3 squares
        mzHyt = Math.max(3,  squaresHigh);  //min maze height is 3 squares
        maze = null;
        resetMaze();
    }
}

3 个答案:

答案 0 :(得分:1)

Vector较旧,但这不是你的问题 - 元素从0开始编号,所以如果你要求元素0,你需要至少有1个元素。

Vector未标记为已弃用,但它会比ArrayList慢,因为它已同步。

答案 1 :(得分:0)

&#34; 0&#34;在错误消息中是超出范围的索引。如果您没有零元素,则Vector为空。

答案 2 :(得分:0)

要么您没有初始化阵列迷宫,要么因为某种原因将其初始化为0。