Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在没有两个数字的情况下生成随机数时,堆栈溢出落在某个范围内_Java_Stack Overflow - Fatal编程技术网

Java 在没有两个数字的情况下生成随机数时,堆栈溢出落在某个范围内

Java 在没有两个数字的情况下生成随机数时,堆栈溢出落在某个范围内,java,stack-overflow,Java,Stack Overflow,我需要编写一个程序来生成一些随机数,而不让两个数落在某个范围内。不幸的是,我需要在学校做这件事,而我能在计算机上使用的唯一语言是Java(否则我会用C++)。我对Java知之甚少,我的程序在生成20个左右的数字后,给了我一个堆栈溢出。有人能解释一下原因吗?这个程序有点难看,但我真的需要尽快把它准备好 import java.io.*; import java.util.*; public class RandomNumbers { public static int GenerateNumbe

我需要编写一个程序来生成一些随机数,而不让两个数落在某个范围内。不幸的是,我需要在学校做这件事,而我能在计算机上使用的唯一语言是Java(否则我会用C++)。我对Java知之甚少,我的程序在生成20个左右的数字后,给了我一个堆栈溢出。有人能解释一下原因吗?这个程序有点难看,但我真的需要尽快把它准备好

import java.io.*;
import java.util.*;

public class RandomNumbers {
public static int GenerateNumber(int previousNumber, int[] numberUsed) {
    Random random = new Random();
    int number = random.nextInt(39);
    if (previousNumber >= 1 && previousNumber <= 9) {
        while (number >= 1 && number <= 9)
            number = random.nextInt(39) + 1;
    } else if (previousNumber >= 10 && previousNumber <= 17) {
        while (number >= 10 && previousNumber <= 17)
            number = random.nextInt(39) + 1;
    } else if (previousNumber >= 18 && previousNumber <= 32) {
        while (number >= 18 && previousNumber <= 32)
            number = random.nextInt(39) + 1;
    } else if (previousNumber >= 33 && previousNumber <= 41) {
        while (number >= 32 && number <= 41)
            number = random.nextInt(39) + 1;
    }
    return number;
}

public static void main(String[] args) {
    int[] numberUsed;
    numberUsed = new int[40];
    for (int i = 0; i < 40; ++i) {
        numberUsed[i] = 0;
    }
    int previousNumber = 0;
    for (int y = 0; y < 40; ++y) {
        int number = 1;
        while (numberUsed[ number = GenerateNumber
                         (previousNumber, numberUsed) ] != 0);
        numberUsed[number] = 1;
        previousNumber = number;
        System.out.println(y);
    }
}
}
import java.io.*;
导入java.util.*;
公共类随机数{
公共静态int-GenerateNumber(int-previousNumber,int[]numberUsed){
随机=新随机();
整数=random.nextInt(39);

如果(previousNumber>=1&&previousNumber=1&&number=10&&previousNumber=10&&previousNumber=18&&previousNumber=18&&previousNumber=33&&previousNumber=32&&number从零输出数组开始,逐渐用1填充,从不将其重置为0。当数组的大多数元素为非零时,则有一个0很有可能在非常深的嵌套中递归调用
GenerateNumber
,这就是您所经历的


另外,在
GenerateNumber
中,您永远不会更改
previousNumber
,因此无论生成的随机数是多少,您都会沿着相同的路径前进。

在看了一会儿之后,我想我找到了一个可行的解决方案。它仍然很难看,但您似乎对此没有意见

public static int GenerateNumber(int previousNumber, 
                                int[] numberUsed) {
    Random random = new Random();
    int number = random.nextInt(39);
    while (numberUsed[number] != 0) {
        number = random.nextInt(39);
        if (previousNumber >= 1 && previousNumber <= 9) {
            while (number >= 1 && number <= 9)
                number = random.nextInt(39) + 1;
        } else if (previousNumber >= 10 && previousNumber <= 17) {
            while (number >= 10 && previousNumber <= 17)
                number = random.nextInt(39) + 1;
        } else if (previousNumber >= 18 && previousNumber <= 32) {
            while (number >= 18 && previousNumber <= 32)
                number = random.nextInt(39) + 1;
        } else if (previousNumber >= 33 && previousNumber <= 41) {
            while (number >= 32 && number <= 41)
                    number = random.nextInt(39) + 1;
        }
    }
    return number;
}
public static int GenerateNumber(int previousNumber,
int[]数字(如所示){
随机=新随机();
整数=random.nextInt(39);
while(numberUsed[number]!=0){
数字=随机数。nextInt(39);

如果(previousNumber>=1&&previousNumber=1&&number=10&&previousNumber=10&&previousNumber=18&&previousNumber=18&&previousNumber=33&&previousNumber=32&&number您的函数最终将出现返回主函数的问题

在中,您将面临一个递归问题

if (numberUsed[number] != 0) {
    return GenerateNumber(previousNumber, numberUsed);
}
当数组被1填满时,它将继续执行函数调用,而不是实际成功返回。它将递归执行函数,最终导致堆栈溢出

当您再次调用该函数时,您的参数(previousNumber和numberUsed)与上次执行的参数相同,没有任何变化。由于命中非零的几率非常高,因此您会不断遇到相同的问题,因此递归将永远堆积起来,最终崩溃


您应该去掉函数中的if语句,只需将数字返回main并在那里进行检查。

由于方法/构造函数等的重叠,会发生堆栈溢出

if (numberUsed[number] != 0) {
        return GenerateNumber(previousNumber, numberUsed);
    }
这段代码在GenerateNumber方法中,它一直在调用同一个方法。这就是原因。如果您想检查它,请删除该部分并重试,它将可以正常编译。要消除这一点,请取消上述过程


您可以通过使用循环、while循环,并将所有if-else语句放在该循环中来完成此操作。

此代码检测到一个死胡同,并不断重新启动,直到它到达终点(通常只进行一次或两次重试)。它还直接从收集到的允许选择序列中选择一个随机数,因此任何一次尝试都不会出现随机运行时

import java.util.Arrays;
import java.util.BitSet;
import java.util.Random;

public class RandomNumberGenerator {
  static final Random random = new Random();
  static final BitSet usedNumbers = new BitSet(40);
  static final int[] ticks = {0, 1, 10, 18, 33, 41};
  static int previousNumber;

  public static int generateNumber() {
    for (int i = 1; i < ticks.length; i++)
      if (previousNumber < ticks[i])
        return generateOutsideRange(ticks[i-1], ticks[i]);
    return generateOutsideRange(0, 0);
  }

  static int generateOutsideRange(int low, int high) {
    final int[] numsToChoose = new int[40];
    int choiceLimit = 0;
    for (int i = (low > 1? 1 : high); i < 41; i = (++i == low? high : i))
      if (!usedNumbers.get(i)) numsToChoose[choiceLimit++] = i;
    if (choiceLimit == 0) throw new CulDeSacException();
    final int r = numsToChoose[random.nextInt(choiceLimit)];
    usedNumbers.set(r);
    previousNumber = r;
    return r;
  }

  public static void main(String[] args) {
    while (true) try {
      usedNumbers.clear();
      previousNumber = -1;
      final int[] rands = new int[40];
      for (int i = 0; i < rands.length; i++) rands[i] = generateNumber();
      System.out.println(Arrays.toString(rands));
      break;
    } catch (CulDeSacException e) { System.out.println("Retry"); }
  }
}

class CulDeSacException extends RuntimeException {}
导入java.util.array;
导入java.util.BitSet;
导入java.util.Random;
公共类随机数生成器{
静态最终随机=新随机();
静态最终位集UsedNumber=新位集(40);
静态final int[]ticks={0,1,10,18,33,41};
静态整数;
公共静态int-generateNumber(){
对于(int i=1;i1?1:高);i<41;i=(++i==低?高:i))
如果(!usedNumbers.get(i))numsToChoose[choiceLimit++]=i;
如果(choiceLimit==0)抛出新的CulDeSacException();
final int r=numsToChoose[random.nextInt(choiceLimit)];
已使用的数字集(r);
前一个数字=r;
返回r;
}
公共静态void main(字符串[]args){
虽然(正确)尝试{
usedNumbers.clear();
前一个数字=-1;
最终整数[]随机数=新整数[40];
对于(int i=0;i
这是被监视的行为吗?“洗牌数组”

ArrayList number=new ArrayList();
int[]加扰=新int[40];
随机rnd=新随机();

对于(int i=0;iSerially?我希望我会很幸运,但这不会发生:(那么你认为我应该如何解决这个问题?你可以将代码更改为使用循环而不是递归(当数组中大部分都是1时,仍然需要一段时间才能完成)或者保留一个
向量
设置
尚未使用的数字,并仅从中选择。因此,请确保生成的数字在0-39范围内,以便在
数字使用[number]中访问40元素数组的整个范围
它挂起在一个无限循环中,在这种情况下,
number
无法正常前进。谢谢,我编辑了我的程序,并注意到您发布了以下内容:)不幸的是,由于某种原因,我没有得到足够的数字来输出。在您的代码中,您缺少的数字=random。nextInt(39);while循环中的行。您需要重新考虑一下:数组开始时填充了零(
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    int[] scrambled = new int[40];
    Random rnd = new Random();
    for(int i=0;i<scrambled.length;i++){
        numbers.add(i+1);
    }
    int idx=0;
    while(!numbers.isEmpty()){
        int pos = rnd.nextInt(numbers.size());

        scrambled[idx] = numbers.get(pos);
        numbers.remove(pos);

        idx++;
    }
    for(int i=0;i<scrambled.length;i++){
        System.out.println(scrambled[i]);
    }