1

又是我。我正在尝试制作一个非常简单的战舰游戏。现在我想用至少一个空闲单元分隔船只。看图片

在此处输入图像描述

正如你所看到的,边缘完全没有运输,这使得可用的放置数量要小得多(或者更少?对不起我的英语不好)。

“字段”只是一个 int[10][10] 数组。

我有一个非常粗鲁的方法来检查是否可以放置船:(IS_WATER const = 0)

private static boolean checkIfShipAvailable(int x, int y, int dir, int length) {
         int counter = 0;
        switch(dir) {
        case DIRECTION_RIGHT:
            try {
                if(field[x-1][y] == IS_WATER) counter++;     
                if(field[x-1][y-1] == IS_WATER) counter++;    
                if(field[x-1][y+1] == IS_WATER) counter++;    
                if(field[x][y-1] == IS_WATER) counter++;      
                if(field[x][y+1] == IS_WATER) counter++;     
                if(field[x+1][y-1] == IS_WATER) counter++;    
                if(field[x+1][y+1] == IS_WATER) counter++;    

                if(field[x+length-1][y-1] == IS_WATER) counter++;
                if(field[x+length-1][y+1] == IS_WATER) counter++;
                if(field[x+length][y] == IS_WATER) counter++;
                if(field[x+length][y-1] == IS_WATER) counter++;
                if(field[x+length][y+1] == IS_WATER) counter++;

            } catch (IndexOutOfBoundsException e) {
                counter++;
            }
            Log.d(TAG, "Direction: Right. Counter = " + counter);
            if (counter == 12)
                return true;
            break;

        case DIRECTION_DOWN:
            try {
                if(field[x-1][y-1] == IS_WATER) counter++ ;
                if(field[x][y-1] == IS_WATER) counter++ ;
                if(field[x+1][y-1] == IS_WATER) counter++ ;
                if(field[x-1][y] == IS_WATER) counter++ ;
                if(field[x+1][y] == IS_WATER) counter++ ;
                if(field[x-1][y+1] == IS_WATER) counter++ ;
                if(field[x+1][y+1] == IS_WATER) counter++ ;

                if(field[x-1][y+length-1] == IS_WATER) counter++ ;
                if(field[x+1][y+length-1] == IS_WATER) counter++ ;
                if(field[x-1][y+length] == IS_WATER) counter++ ;
                if(field[x][y+length] == IS_WATER) counter++ ;
                if(field[x+1][y+length] == IS_WATER) counter++ ;

            } catch (IndexOutOfBoundsException e) {
                counter++;
            }
            Log.d(TAG, "Direction: Down. Counter = " + counter);
            if (counter  == 12)
                return true;
            break;
        }
        return false;
    }

那是2-4个细胞船。对于 1 单元船:

private static boolean checkIfOneAvailable(int x, int y) {
         int counter = 0;
         try {
                if(field[x-1][y-1] == IS_WATER) counter++ ;
                if(field[x][y-1] == IS_WATER)counter++ ;
                if(field[x+1][y-1] == IS_WATER) counter++ ;
                if(field[x-1][y] == IS_WATER) counter++ ;
                if(field[x+1][y] == IS_WATER) counter++ ;
                if(field[x-1][y+1] == IS_WATER) counter++ ;
                if(field[x+1][y+1] == IS_WATER) counter++ ;
                if(field[x][y+1] == IS_WATER) counter++ ;   
        } catch (IndexOutOfBoundsException e) {     
          counter++;
        } 
         if (counter == 8) 
             return true;
        return false;

     }

你能告诉我,错误在哪里,我怎样才能让船甚至放在边缘?

4

2 回答 2

2

不要试水。测试是否有另一艘船在那里。像这样:

private static boolean checkIfOneAvailable(int x, int y) {        
    if(x!=0 && y!=0 && field[x-1][y-1] == IS_SHIP) return false;
    if(y!=0 && field[x][y-1] == IS_SHIP) return false;
    ...
    return true;
 }

请注意,我已将数组边界检查添加到条件中。使用异常进行流控制被认为是一个坏习惯,主要是因为它很慢。使用这种方法时,您还可以从以下事实中获得性能提升,即您不必总是检查所有周围的字段。一旦你找到一个碰撞,你就会得到结果。

此外,为大型船只复制粘贴代码也没有任何意义。在您放置船之前,您仍然可以对较大船的每个字段进行相同的检查:

private static boolean checkIfAvailable(int x, int y, int dir, int length){
    for (int i = 0; i<length; i++){
        switch (dir) {
            case DIRECTION_RIGHT:
                if (!checkIfOneAvailable(x+i,y))
                    return false;
                break;
            case DIRECTION_DOWN:
                if (!checkIfOneAvailable(x,y+i))
                    return false;
                break;
        }             
    }
    return true;
}
于 2013-06-11T15:39:53.123 回答
1

如果 aIndexOutOfBoundsException发生,则所有后面if(field...的行都catch不会执行,并且计数器不再增加。

更好的解决方案:创建一个获取坐标并返回field[x][y]值或特殊OUT_OF_BOUNDS值的方法(通过捕获IndexOutOfBoundsException或检查边界)

于 2013-06-11T15:33:30.577 回答