战舰射击[Java]

时间:2016-12-06 22:07:38

标签: java

目标是尽量减少我在随机生成的战舰板上拍摄的镜头数量。我的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方法返回一个布尔值。

问题是效率是相同的,而不是跳过已经错过或被击中的元素。

3 个答案:

答案 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值存储在两个位置:ij以及shot变量。在while循环中,您可以将新值分配给ij,但不会分配给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提供的答案更有价值,你应该遵循它。

如果您认为我说的话不正确,请告诉我。