目标是尽量减少我在随机生成的战舰板上拍摄的镜头数量。我的fireShot()方法应该确定我的2D数组中的点是否已被击中,未命中或击中。
public boolean fireShot()
{
Random rand = new Random();
int i = rand.nextInt(10); //generate 2 random numbers for rows and columns
int j = rand.nextInt(10);
Point shot = new Point(i,j);
while (mapState[i][j] != empty){
j = rand.nextInt(10);
i = rand.nextInt(10);
mapState[i][j] = shotAt;
}
boolean hit = battleShip.shoot(shot);
if(hit == false){
mapState[i][j] = miss;
}
else if(hit == true){
mapState[i][j] = hitInt;
huntMode(i,j);
}
return false;
}
如果该点击中船只,则battleShip.shoot方法返回一个布尔值。
问题是效率是相同的,而不是跳过已经错过或被击中的元素。
答案 0 :(得分:2)
您的代码效率不高,因为它试图随机查找未使用的点,一旦地图变得越来越多,这将需要越来越多的尝试。
因此,您应该尽量避免在整个地图中获取随机数,但只能在尚未使用的点的子集中。
为此,您可以创建List
未使用Points
并使用rand
获取此List
中的索引。该索引处的对象将成为未被捕获的点。完成后,您从Point
中删除List
,以便下一个rand
仍会生成指向未使用点的索引。
例如,您首先生成List
未使用的点:
int maxX = 10;
int maxY = 10;
// create the list with all the map positions: (0,0)(0,1)...(9,9)
List<Point> pointsToTry = new ArrayList<Point>();
for (int iy = 0; iy < maxY; iy++) {
for (int ix = 0; ix < maxX; ix++) {
pointsToTry.add(new Point(ix, iy));
}
}
然后在每一次拍摄中你只需:
// get a random index of an unused point
int i = rand.nextInt(pointsToTry.size());
// remove that point from the list so it will not be picked again
Point shot = pointsToTry.remove(i);
答案 1 :(得分:1)
因此,您将I和J值存储在两个位置:i
和j
以及shot
变量。在while循环中,您可以将新值分配给i
和j
,但不会分配给shot
,因此当您调用battleShip.shoot()
时,它始终会设置为原始值。我建议您在致电shot
之前不要创建Point
battleShip.shoot()
。另外,我建议使用do {} while()
循环代替while
,这样您就不必复制随机调用。你也不需要检查hit == true
你可以做if (hit) ... else ...
这样的事情:
public boolean fireShot() {
Random rand = new Random();
int i, j;
do {
j = rand.nextInt(10);
i = rand.nextInt(10);
} while (mapState[i][j] != empty);
mapState[i][j] = shotAt;
boolean hit = battleShip.shoot(new Point(i, j));
if (hit) {
mapState[i][j] = hitInt;
huntMode(i, j);
} else {
mapState[i][j] = miss;
}
return false;
}
答案 2 :(得分:0)
我已删除了之前的答案,现在正试图解决您的代码遇到的问题。
int i = rand.nextInt(10); //generate 2 random numbers for rows and columns
int j = rand.nextInt(10);
while (mapState[i][j] != empty){
j = rand.nextInt(10);
i = rand.nextInt(10);
mapState[i][j] = shotAt;
}
在上面的代码段中,例如i = 4 and j = 6
如果之前已经拍摄过,那么您将输入while循环,因为条件为mapState[i][j] != empty
empty = 0
。然后再次生成一对数字并分配shootAt
,然后再次检查while循环的条件,由于该循环内的mapState[i][j] = shotAt;
语句,该循环始终为false。 (你应该在这里遇到无限循环)
唯一可以从fireShot()
方法返回值的时间是:如果对于在进入while循环之前生成的随机数对i, j
,则电路板状态为空(从未拍摄过)。对?希望你现在能理解这个错误。这就是@YonaAppletree以下列方式修改代码的原因。
Random rand = new Random();
int i, j;
do {
j = rand.nextInt(10);
i = rand.nextInt(10);
} while (mapState[i][j] != empty);
mapState[i][j] = shotAt;
现在这个do-while循环会从棋盘上找到一个空单元格来射击:你实际上想要做什么。但@LorisSecuro提供的答案更有价值,你应该遵循它。
如果您认为我说的话不正确,请告诉我。