我试图确保没有两个类的实例具有相同的优先级/ id值。我目前正试图为每个优先级值保存布尔值,但在我的单元测试中从不抛出异常。为什么这段代码不起作用?
public abstract class AbstractCard implements Card {
private int priority;
protected Robot robot;
private static boolean[] prioritiesUsed = new boolean[1000]; // defaults to false
...[omitted code]
protected AbstractCard(int lowPriority, int highPriority) {
// TODO: this doesn't work!
// different instances can have the same priority right now
// that shouldn't be allowed, so something's broken somewhere here!
// this code will still work as good as the placeholder code we had, so I'm pushing this broken code
Random random = new Random();
// try a few times to get a random priority that hasn't been used before
for (int tries = 0; tries < 10; tries++) {
// get random priority p in range low <= p <= high
this.priority = random.nextInt((highPriority - lowPriority) + 1) + lowPriority;
// is this priority already taken?
if (prioritiesUsed[this.priority] == false) {
prioritiesUsed[this.priority] = true;
return;
}
}
// screw randomizing, it didn't work. Let's just increment untill we find a free one.
int infiniteLoopDetector = this.priority - 1;
while (prioritiesUsed[this.priority]) {
this.priority++;
if (this.priority > highPriority) { // about to leave range, wrap around and try from lower bound
this.priority = lowPriority;
}
if (this.priority == infiniteLoopDetector) {
throw new DeckPriorityIntervalFilledException(
String.format("All priority values between %d and %d are already taken by other cards",
lowPriority, highPriority));
}
}
}
这里是单元测试,使用intellij中的groovy
注意:class MoveCard extends AbstractCard
void testConstructor() {
// try to create 101 cards inside a 100 card interval
try {
for (int i = 0; i < 100; i++) {
new MoveCard(42, 141); // 42 <= priority <= 141
}
} catch (RuntimeException e) {
fail("exception thrown: " + e.toString());
}
// and add the 101st one, that should throw an exception
try {
AbstractCard ac = new MoveCard(42, 141);
println(ac.priority);
ac = new MoveCard(42, 141);
println(ac.priority);
ac = new MoveCard(42, 141);
println(ac.priority);
ac = new MoveCard(42, 141);
println(ac.priority);
ac = new MoveCard(42, 141);
println(ac.priority);
fail("exception wasn't thrown!");
} catch (RuntimeException e) {
// all ok
}
}
答案 0 :(得分:1)
您根本就没有设置
prioritiesUsed[this.priority] = true;
用while
循环后尝试优先级。
一般提示:
在调试过程中,我强烈建议使用使用特定随机种子初始化的公共Random
实例。此实例将始终提供相同的随机数序列,使运行可重现。因此,用
Random
实例
private static Random random = new Random(0);
然而,你的方法是......不是很优雅。正如其他人所指出的那样,用Set
来管理优先事项会容易得多。如建议的那样,您可以使用工厂来封装优先级的管理,但代码粗略看起来像这样:
abstract class AbstractCard
{
int priority;
private static Set<Integer> usedPriorities = new LinkedHashSet<Integer>();
private static Random random = new Random(0);
protected AbstractCard(int lowPriority, int highPriority)
{
Set<Integer> availablePriorities = new LinkedHashSet<Integer>();
for (int i = lowPriority; i <= highPriority; i++)
{
availablePriorities.add(i);
}
availablePriorities.removeAll(usedPriorities);
if (availablePriorities.size() == 0)
{
throw new RuntimeException(String.format(
"All priority values between %d and %d "
+ "are already taken by other cards", lowPriority,
highPriority));
}
List<Integer> priorities = new ArrayList<Integer>(availablePriorities);
int index = random.nextInt(priorities.size());
this.priority = priorities.get(index);
usedPriorities.add(this.priority);
}
}