线程“main”中的异常java.lang.IllegalArgumentException:StdRandom.uniform中的参数N必须为正(StdRandom.java:119)

时间:2016-05-03 00:14:35

标签: java eclipse junit maze

我是这个网站的新手,如果我的问题有任何问题,请纠正我。我一直收到这个错误,我不完全确定我的程序出了什么问题:

  

线程“main”中的异常java.lang.IllegalArgumentException:参数N必须为正

at StdRandom.uniform(StdRandom.java:119)
at Maze.chooseRandomlyFrom(Maze.java:52)
at Maze.expandMaze(Maze.java:136)
at Maze.main(Maze.java:193)**

我在IDE(eclipse)中运行了JUnit测试但是我无法追踪错误的来源。非常感谢任何帮助或指导,并感谢您花时间查看代码。这是我正在使用的。我尽可能清楚地为每种方法添加了评论。

public class Maze {
public static final int EAST = 1;
public static final int NORTH = 0;
public static final int[][] OFFSETS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
public static final int SOUTH = 2;
public static final int WEST = 3;

  //Purpose: Modifies passage to contain a one-way passage from location a to location
  //b. Assumes these two locations (arrays of two numbers) are adjacent.
  //Parameters: boolean[][][] passages, int[] a, int[] b
  //Return: N/A
public static void addPassage(boolean[][][] passages, int[] a, int[] b) 
{
        int ax = a[0];
        int ay = a[1];
        int bx = b[0];
        int by = b[1];
        if (by == ay + 1) {
          passages[ax][ay][0] = true;
        } else if (bx == ax + 1) {
          passages[ax][ay][1] = true;
        } else if (by == ay - 1) {
          passages[ax][ay][2] = true;
        } else {
          passages[ax][ay][3] = true;
        }
}

  //Purpose: Gets array of pairs containing start and all locations in the list. 
  //Parameters: int[] start, int[][] list
  //Return: Returns a new array of pairs containing start followed by all of the locations in list.
public static int[][] addToFront(int[] start, int[][] list) 
{
    int[][] path = new int[list.length + 1][];
    path[0] = start;
    for (int i = 1; i < path.length; i++) {
      path[i] = list[(i - 1)];
    }
    return path;
}

  //Purpose: Gets random one from the first element of the list
  //Parameters: int[][] list, int n
  //Return: Returns a random one of the first n elements of list.
public static int[] chooseRandomlyFrom(int[][] list, int n) 
{
    return list[StdRandom.uniform(n)];
}

  //Purpose: Gets pair and compares to first number as one of the first n element 
  //Parameters: int[] pair, int[][] list, int n
  //Return: Returns true if pair, assumed to be an array of two numbers, has the same 
  //numbers as one of the first n elements of list.
public static boolean contains(int[] pair, int[][] list, int n) 
{
    for (int i = 0; i < n; i++) {
          if ((pair[0] == list[i][0]) && (pair[1] == list[i][1])) {
            return true;
          }
        }
        return false;
}

  //Purpose: Will draw the maze
  //Parameters: boolean[][][] passages
  //Return: N/A
public static void drawMaze(boolean[][][] passages) 
{
    StdDraw.clear(StdDraw.PINK);
    StdDraw.setPenColor(StdDraw.WHITE);
    int width = passages.length;
    StdDraw.setPenRadius(0.75 / width);
    // Draw passages
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < width; y++) {
            if (passages[x][y][NORTH] || (y + 1 < width && passages[x][y + 1][SOUTH])) {
                StdDraw.line(x, y, x, y + 1);
            }
            if (passages[x][y][EAST] || (x + 1 < width && passages[x + 1][y][WEST])) {
                StdDraw.line(x, y, x + 1, y);
            }
        }
    }
    // Draw entrance and exit
    StdDraw.line(0, 0, -1, 0);
    StdDraw.line(width - 1, width - 1, width, width - 1);
    StdDraw.show(0);
}

  //Purpose: Will draw the maze solution
  //Parameters: int[][] path, int width
  //Return: N/A
public static void drawSolution(int[][] path, int width) 
{
    StdDraw.setPenColor(); // Black by default
    StdDraw.setPenRadius();
    StdDraw.line(0, 0, -1, 0);
    StdDraw.line(width - 1, width - 1, width, width - 1);
    for (int i = 0; i < path.length - 1; i++) {
        StdDraw.line(path[i][0], path[i][1], path[i + 1][0], path[i + 1][1]);
    }
    StdDraw.show(0);
}

  //Purpose: Checks if here's neighbor in direction (called there) is in unexplored. If so, adds a passage from here 
  //to there and returns there. If not,returns null.
  //Parameters: boolean[][][] passages, int[][] unexplored, int n, int[] here, int direction otherwise.
public static int[] expandLocation(boolean[][][] passages, int[][] unexplored, int n, int[] here, int direction) 
{
    int[] there = new int[2];
    here[0] += OFFSETS[direction][0];
    here[1] += OFFSETS[direction][1];
    if (contains(there, unexplored, n))
    {
      addPassage(passages, here, there);
      return there;
    }
    return null;
}

  //Purpose: Chooses "here" to be either lastExploredLocation (if it is not null) or a random location in 
  //frontier. If possible, adds a passage from "here" to a location "there" in unexplored, then moves "there" from unexplored to
  //frontier. If not, moves "here" from frontier to done.
  //Parameters: boolean[][][] passages, int[][] done, int[][] frontier, int[][] unexplored, int[] counts, int[] lastExploredLocation
  //Return: N/A
public static int[] expandMaze(boolean[][][] passages, int[][] done, int[][] frontier, int[][] unexplored, int[] counts, int[] lastExploredLocation) 
{
    int[] here;
    if (lastExploredLocation == null) {
      here = chooseRandomlyFrom(frontier, counts[1]);
    } else {
      here = lastExploredLocation;
    }
    int direction = StdRandom.uniform(4);
    for (int i = 0; i < 4; i++)
    {
      int[] there = expandLocation(passages, unexplored, counts[2], here, direction);
      if (there != null)
      {
        frontier[counts[1]] = there;
        counts[1] += 1;
        remove(there, unexplored, counts[2]);
        counts[2] -= 1;

        return there;
      }
      direction = (direction + 1) % 4;
    }
    done[counts[0]] = here;
    counts[0] += 1;
    remove(here, frontier, counts[1]);
    counts[1] -= 1;
    return null;

}
  //Purpose: Draws then solves maze
  //Parameters: String[] args
  //Return: N/A
public static void main(String[] args) 
{
    int width = 20;
    StdDraw.setXscale(-0.5, width - 0.5);
    StdDraw.setYscale(-0.5, width - 0.5);
    StdDraw.show(0);
    boolean[][][] passages = new boolean[width][width][4];
    // Initially, no locations are done
    int[][] done = new int[width * width][];
    // The frontier only contains {0, 0}
    int[][] frontier = new int[width * width][];
    frontier[0] = new int[] { 0, 0 };
    // All other locations are in unexplored
    int[][] unexplored = new int[width * width][];
    // Number of nodes done, on the frontier, and unexplored
    int[] counts = { 0, 1, width * width - 1 };
    int i = 0;
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < width; y++) {
            if (x != 0 || y != 0) {
                unexplored[i] = new int[] { x, y };
                i++;
            }
        }
    }
    // As long as there are unexplored locations, expand the maze
    int[] lastExploredLocation = null;
    while (counts[2] > 0) {
        lastExploredLocation = expandMaze(passages, done, frontier, unexplored, counts, lastExploredLocation);
        drawMaze(passages);
        StdDraw.show(25);
    }
    // Solve the maze
    int[][] solution = solve(passages, new int[] { 0, 0 }, new int[] { width - 1, width - 1 });
    drawSolution(solution, width);
}

  //Purpose: Modifies list so that pair is replaced with the (n - 1)th element of list. Assumes pair is an 
  //array of two numbers that appears somewhere in list. Thus, when this method is done, the first n - 1 element of list are
  //the same as the first n elements of the old version, but with pair removed and with the order of elements potentially different.
  //Parameters: int[] pair, int[][] list, int n
  //Return: N/A
public static void remove(int[] pair, int[][] list, int n) 
{
    for (int i = 0; i < n; i++) {
          if ((pair[0] == list[i][0]) && (pair[1] == list[i][1]))
          {
            list[i] = list[(n - 1)];
            return;
          }
        }
}

  //Purpose: Gets a return path from start to finish
  //Parameters: boolean[][][] passages, int[] start, int[] goal
  //Return: Returns a path (sequence of locations) leading from start to goal in passages or null if there is no such path.
public static int[][] solve(boolean[][][] passages, int[] start, int[] goal) {
    if ((start[0] == goal[0]) && (start[1] == goal[1])) {
          return new int[][] { goal };
        }
        for (int d = 0; d < 4; d++) {
          if (passages[start[0]][start[1]][d] != false)
          {
            int[] next = { start[0] + OFFSETS[d][0], start[1] + OFFSETS[d][1] };
            int[][] restOfPath = solve(passages, next, goal);
            if (restOfPath != null) {
              return addToFront(start, restOfPath);
            }
          }
        }
        return null;
      }
}

1 个答案:

答案 0 :(得分:0)

当您将参数'n'传递给。时 Maze.chooseRandomlyFrom(Maze.java:52)中的StdRandom.uniform()你传递的参数是否定的。根据错误消息,参数必须为正。这可能是因为在expandMaze期间,您将计数[1]分配为比其当前值小1(计数[1] - = 1;),这最终将导致负数。似乎只要计数[2]&gt;就会反复调用该方法。 0,在某些情况下必须是足够迭代的情况,例如计数[1]变为负数。

也许在调用此StdRandom.uniform()方法之前,您应该采用计数[1]的绝对值来确保它始终为正。 Math.abs(计数[1])应该可以解决问题。