有一个java.lang.ArrayIndexOutOfBoundsException:-1错误。循环淹水

时间:2015-02-27 03:25:47

标签: java recursion indexoutofboundsexception flood-fill

我正在尝试制作一个洪水填充游戏,将数字打印到控制台窗口,并允许用户选择一个数字,以便填充"具有相同编号的2D阵列。目标是让2D阵列充满你的颜色。我使用4向递归方法来填充这些数字。每次我运行它,并尝试输入一个"颜色,"它抛出了这个错误:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
     at Board.floodFill(Board.java:57)
     at Board.floodFill(Board.java:68)
     at Board.move(Board.java:47)
     at FloodIt.main(FloodIt.java:30)

这是我的代码:

class FloodIt {

    public static void main(String args[]) {
        Scanner scan=new Scanner(System.in);
        System.out.println("Welcome to the Flood-It Game.");
        System.out.println("*****************************");
        System.out.println("How large of a board would you like?");
        System.out.println("I would suggest sizes between 3x3 and 20x20.");
        System.out.println("And colors between 3 and 6.");
        String again="";
        do {
            System.out.print("Enter the one digit number of the board width (3-20): ");
            int size=Integer.parseInt(scan.nextLine());
            System.out.print("Enter the number of colors (3-6): ");
            int numColors=Integer.parseInt(scan.nextLine());
            Board board=new Board(size,numColors);
            while(!board.finished()) {
                System.out.print(board);
                System.out.print("What color do you choose? ");
                int color=Integer.parseInt(scan.nextLine());
                board.move(color);
            }
            System.out.println("Nice job, you finished in "+board.numMoves());
            System.out.print("Would you like to play again (Y/N)? ");
            again=scan.nextLine();
        } while (again.equalsIgnoreCase("Y"));
    }
}

import java.util.Random;

/**The board class for the Flood-It game.  This class implements a NxN board filled with numColors colors.
 * The class implements several methods to allow the playing of the game.
 */
class Board {
    private int moves;
    private int[][] board;//a 2D array
    Random rand = new Random();

    /**Constructs a new sizeXsize board filled where each element on the board is a random number between 0
     * and numcolors.  Also initializes the number of moves to zero.
     * @param size the size of the board
     * @param numColors the number of possible entries on the board
     */
    public Board(int size,int numColors) {
        moves=0;
        board = new int[size][size];
        for(int row=0;row<board.length;row++){
            for(int col = 0;col<board[row].length;col++){
                board[row][col]=rand.nextInt(numColors);
            }
        }
    }


    /**Updates the board to fill (from the top left corner) with a specificed color.  
     * Filling stops when any other color is hit besides the one in the top left corner.
     * Play the game at http://floodit.cs.bris.ac.uk/About.aspx to get a better understanding of what
     * this method should do.  You will probably also want to take a look at the algorithm described
     * at http://en.wikipedia.org/wiki/Flood_fill which describes what this method should do.
     * You are free to have this method call other methods (I would recommend creating a private method that
     * this method calls.).
     * @param color the new color to flood the board with.
     */

    public void move(int color) {
        floodFill(0,0,board[0][0],color);
        moves++;

    }

    private void floodFill(int row, int col, int origColor,int newColor){
        //base case
        if(origColor==newColor){
            return;
        }
        if(board[row][col]!=origColor){
            return;
        }
        if(row<0||col<0){
            //do nothing
            return;
        }


        board[row][col]=newColor;

        floodFill(row,col-1,origColor,newColor);
        floodFill(row,col+1,origColor,newColor);
        floodFill(row-1,col,origColor,newColor);
        floodFill(row+1,col,origColor,newColor);    
    }


    /**returns true if the board is not completely filled with a single color.
     * Otherwise it returns false.
     * @return true if board is all one color
     */
    public boolean finished() {
        //TODO finish this method

        return false;
    }


    /**returns how many times the move() method has been called.
     * @return the number of times the move() method has been called.
     */
    public int numMoves() {
        return moves;
    }


    /**Returns a string representation of the board.  Use tabs between elements of the board.
     * And have every row of the board be a seperated by a newline character.
     * Example:
     * "1\t0\t3\t\n2\t0\t2\t\n1\t0\t1\t\n"
     * @return a String representation of the board
     */
    public String toString() {
        String result = "";
        for(int row=0;row<board.length;row++){
            for(int col = 0;col<board[row].length;col++){
                result += board[row][col]+"\t";
            }
            result+="\n";
        }return result; 
    }
}

2 个答案:

答案 0 :(得分:1)

floodFill方法中,在致电row之前,您不会检查colboard[row][col]=newColor是否在界限范围内。

您的代码:

if(row<0||col<0){
        //do nothing
        return;
}

应放在函数的较高位置,以便在board[row][col]=newColor之前进行检查。它还需要检查它是否大于数组的宽度和高度。

正确的代码:

if(row<0||col<0||row>=board.length||col>=board[0].length)
{
   return;
}

答案 1 :(得分:0)

您检查

if(row<0||col<0)

因此rowcol都可以 0

然后你有

    floodFill(row,col-1,origColor,newColor);
    floodFill(row,col+1,origColor,newColor);
    floodFill(row-1,col,origColor,newColor);
    floodFill(row+1,col,origColor,newColor);  

因此,两者中的任何一个都可能成为-1

您的代码具有以下验证顺序:

   if(board[row][col]!=origColor){
        return;
    }
    if(row<0||col<0){
        //do nothing
        return;
    }

在第一个if中,您可以拥有[-1]。如果你交换两个if,它就不可能。