我需要编写一个程序来生成一些随机数,而不会有两个数字落在一定范围内。不幸的是,我需要在学校这样做,我可以在计算机上使用的唯一语言是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);
}
}
}
编辑:好的,现在,由于某种原因,当我包含while循环时,for循环(y作为计数器的循环)没有运行40次。有人可以解释为什么会这样吗?
答案 0 :(得分:2)
你的功能最终会有一个问题,永远不会回到主。
您将面临
中的递归问题if (numberUsed[number] != 0) {
return GenerateNumber(previousNumber, numberUsed);
}
当数组得到1时,这将继续执行函数调用而不是实际成功返回。它会以递归方式执行函数,最终导致堆栈溢出。
再次调用该函数时,您的参数(previousNumber和numberUsed)与上次执行相同,没有任何变化。你继续遇到同样的问题,因为击中非零的机会是如此之高,所以递归只是永远堆积起来并最终崩溃。
你应该摆脱函数中的if语句,只需将数字返回main,然后在那里进行检查。
答案 1 :(得分:0)
你从一个零出的数组开始,你逐渐填充1并且永远不会将它们重置为0.当数组的大多数元素都是非零时,你很有可能调用{{1在一个非常深的嵌套中递归,这是你经历的。
此外,您永远不会更改GenerateNumber
中的previousNumber
,因此无论生成的随机数如何,您都将始终沿着相同的路径前进。
答案 2 :(得分:0)
在盯着这一段时间之后,我想我找到了一个有效的解决方案。它仍然非常难看,但你似乎对此很好。
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;
}
另一方面,当你走向列表末尾时,运行时也会很恶劣,但不应该堆栈溢出。现在我想起来也可能是无限循环,你可能需要完全重新设计它。
答案 3 :(得分:0)
StackOverFlow因为方法/构造函数等的重叠而发生。我在这里,
if (numberUsed[number] != 0) {
return GenerateNumber(previousNumber, numberUsed);
}
此代码位于GenerateNumber方法内部,并且继续调用相同的方法。这就是原因。如果你想检查它,删除该部分并尝试,它将编译正常。要摆脱这种情况,请排除上述过程。
你可以通过循环,while循环,并将所有if else语句放在
中来实现答案 4 :(得分:0)
此代码检测到死胡同并继续重新启动直到它到达终点(通常只执行一次或两次重试)。它还直接从收集的允许选择序列中选择一个随机数,因此任何单一尝试都不会有随机运行时间。
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 {}
答案 5 :(得分:0)
这是指定行为吗? &#34;改组阵列&#34;
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]);
}