- 必须有一个单独的战舰(4个单元大小),2个巡洋舰(3个单元大小),3个驱逐舰(2个单元大小)和4艘潜艇(1个单元大小)。不允许任何额外的船只,也不允许缺少船只。
- 每艘船必须是一条直线,除了潜艇,它们只是单个单元格。
- 船不能重叠,但可以与任何其他船接触。
我的方法只是计算大小为2,3,4的船只的所有可能的连接,并确保它们比所需的船只数量更大。这对于每种情况都不起作用,还可以帮助检查是否恰好有20个放置点。问题在于,如果我们有0 1 1 1 1 0 0 0 0 0,它会告诉我它是有效的,尽管它明显不是(因为它是一行和一艘船),当我有以下内容时:应该是错误的,但我的返回值是true->
{0,0,0,0,0,0,0,1,1,0},
{0,0,0,0,0,0,0,1,1,1},
{0,0,0,0,0,0,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0},
{0,1,0,0,1,1,1,0,0,0},
{0,0,0,0,1,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,0,1,1,0},
{0,0,1,0,0,0,0,1,1,0},
或者,应该是错误的,但我的代码返回了真。
{0,1,1,1,0,0,0,0,0,0},
{0,0,0,1,1,1,0,0,0,0},
{0,1,1,1,0,0,0,0,0,0},
{0,0,0,1,1,1,0,0,0,0},
{0,1,1,1,0,1,1,0,0,0},
{0,1,0,0,0,0,1,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
这是一个例子,当代码应该返回true时它可以正常工作:
{1,0,0,0,0,1,1,0,0,0},
{1,1,0,0,0,0,0,0,1,0},
{1,1,0,0,1,1,1,0,1,0},
{1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
但是当我有这个例子时:
{0,0,1,0,0,0,0,1,1,0},
{0,1,1,0,0,0,0,0,0,0},
{1,1,1,1,1,0,0,0,0,1},
{0,0,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,0,0,1},
{0,0,0,0,0,0,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
应该是false,但我的代码返回true。所以我应该如何重构我的代码或者有一个解决方案,当我给定一个棋盘时,我不会真正知道它是否有效,但我的Java程序会知道?
这是我的代码,我尝试了一下,我的方法是制作一个列表,列出从最大到最小检查特定船只的所有变化(最大的将是[4 3 3 2 2 2],不包括1,因为它会显著增加变化的数量,我可以用不同的方式更高效地检查它,最小的变化将是[2 2 2 3 3 4],4最后,它们被重复是因为对于2有x3艘船,所以2 2 2,x2大小3艘船,所以3 3和x1大小4艘船,所以只有一个),这是代码:
import java.util.*;
class Permute{
public static List<int[]> l;
Permute(){
this.l=new ArrayList<int[]>();
}
static void permute(java.util.List<Integer> arr, int k){
for(int i = k; i < arr.size(); i++){
java.util.Collections.swap(arr, i, k);
permute(arr, k+1);
java.util.Collections.swap(arr, k, i);
}
if (k == arr.size() -1){
l.add(arr.stream()
.map(i -> (i == null ? 0 : i))
.mapToInt(Integer::intValue)
.toArray());
}
}
public static List<int[]> get(){
Permute.permute(java.util.Arrays.asList(2,2,2,3,3,4), 0);Collections.reverse(l);
return l;
}
}
public class BF {
private static int[][] fields,copy;
private static int[] ship= {0,0,3,2,1};
public BF(int[][] field) {
fields=field;
// print(field);
this.copy=field;
}
public boolean validate() {
int cnt=counter(fields);
if(cnt!=20)return false;
Permute p= new Permute();//permutation constructor
List<int[]> list=p.get();//gets our specific permution
for (int i = 0; i < list.size(); i++) {//run through each option of our permution list
copy=fields;
ship=new int[]{0,0,3,2,1};//amount of ships needed
boolean flag=check(fields,list.get(i));//checks if the permution variation is true or false
int cnt1=counter(copy);//we checked boats of size 2 3 4 but not 1 which means if its valid then there should be 4 boats left
if(flag && cnt1==4)return true;
}
return false;
}
public static boolean check(int[][] field,int[] ships){
for(int i=0;i<ships.length;i++) {//go through the array and loop through the variation
int num=getBoat(fields, ships[i]);//if the boat is true on the certain boat we are checking
ship[num]--;//then -1 and at the end we want it to be [<=0,0,0,0,0]
}
int counter=0;
for(int i=2;i<ship.length;i++) {
if(ship[i]==0)counter++;//if [0,0,0]
}
if(counter==3) {return true;}//then return true
return false;
}
public static int getBoat(int[][] field,int num) {
int dire=0,r=0,c=0;String dir="row";
for (int col = 0; col < fields[0].length; col++) {
for (int row = 0; row < fields.length; row++) {//loop through each coordinate
if (copy[row][col] == 1) {//check if its part of a boat at the coor
int length=field.length;dir="row";dire=row;
for(int j=0;j<2;j++) {//go horizontal then vertical
if(j==1) {length=field[0].length;dir="col";dire=col;}//change length to vertical
if(dire+num-1<length) {//make sure we don't get outofbounds error
int cnt=0;
for(int i=0;i<num;i++) {//checks each coor according to type of boat we are checking
if(dir.equals("row")) {r=row+i;c=col;}
else if(dir.equals("col")){r=row;c=col+i;}
if(copy[r][c]==1) {//check
cnt++;//copy of battle field becomes 0
}
else copy=fields;//otherwise break this loop since it is not relevant anymore on this coor
if(cnt==num) {
for(int k=0;k<num;k++) {
if(dir.equals("row")) {r=row+k;c=col;}
else if(dir.equals("col")){r=row;c=col+k;}
copy[r][c]=0;//now we know its valid length and make it 0 on the copy
}
return cnt;
}}}} //if num is correct then return it
}
}
}return 0;
}
public static int counter(int[][] f) {// counts amount of tiles on the board with 1's
int cnt=0;
for (int col = 0; col < f[0].length; col++) {
for (int row = 0; row < f.length; row++) {
if (f[row][col] == 1) {
cnt++;
}
}
}
return cnt;
}
public static void print(int[][] field) {//prints the board
for (int row = 0; row < field.length; row++) {
for (int col = 0; col < field[0].length; col++) {
if(col<field[0].length-1 && col!=0) {
System.out.print( field[row][col]+",");
}
else if(col==field[0].length-1){
System.out.print( field[row][col]+"},");
}
else if(col==0) {
System.out.print(" {"+ field[row][col]+",");
}
}
System.out.println("");
}
System.out.println("\n");
}
}
这段代码现在似乎运行良好,但是当它应该返回true时却没有。
以下是一些例子,其中代码应该返回true,但实际上返回了false:
{1,0,0,0,0,1,1,0,0,0},
{1,0,1,0,0,0,0,0,1,0},
{1,0,1,0,1,1,1,0,1,0},
{1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
这里是 true:
{1,0,0,0,0,0,0,0,1,0},
{0,0,1,0,0,1,1,1,1,0},
{0,0,1,1,0,0,0,0,0,0},
{0,0,1,1,1,1,1,0,0,0},
{0,0,1,1,1,0,0,0,0,0},
{0,0,1,0,1,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
这里是 true:
{1,0,0,0,0,1,1,0,0,0},
{1,1,0,0,0,0,0,0,1,0},
{1,1,0,0,1,1,1,0,1,0},
{1,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,1,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
这里是 true:
{1,1,1,0,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0,1,0},
{1,1,0,0,1,1,1,0,1,0},
{1,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,1,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
这里是真的:
{1,0,0,0,0,1,1,0,0,0},
{1,1,0,0,0,0,0,0,1,0},
{1,1,0,0,1,1,1,0,1,0},
{1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
但是代码在这些示例中返回false。
因此,在这个示例中。
{1,1,1,0,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0,1,0},
{1,1,0,0,1,1,1,0,1,0},
{1,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,1,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,0},
它是有效的,因为:
[![enter image description here][1]][1]
但我的代码选择了尺寸的第一个选项,这就是我的代码返回false的原因-
[![enter image description here][2]][2]
那么我需要添加什么来解决这个问题?
public class BF {
private static int[][] fields;
public BF(int[][] field) {
fields=field;
print(field);
}
public boolean validate() {
int cnt=counter(fields);
if(cnt!=20)return false;
return checkBoard(fields, new int[]{4,3,3,2,2,2},0,new int[] {3,2,1});
}
public static boolean checkBoard(int[][] board,int[] SizePlacement,int k,int[] shipAmount){
if (counter(board)==4 ) {
return true;
}
int cnt=0;//SizePlacement={4,3,3,2,2,2}, ship(changes)={3,2,1}, k(starts at 0) is placement in ships[]
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[0].length; col++) {
if(board[row][col]==1 && row+SizePlacement[k]<board.length) {//vertically
cnt=1;
for(int i=1;i<SizePlacement[k];i++) {//check vertically
if(board[row+i][col]==1) {cnt++;}
}
if(cnt>=SizePlacement[k]) {
int[][] newBoard = deepcopy(board);
newBoard= remove(newBoard , row, col, SizePlacement[k], "ver");
shipAmount[SizePlacement[k]-2]--;
if(shipAmount==new int[]{0,0,0}) {return true;}
if(k+1<SizePlacement.length && checkBoard(newBoard,SizePlacement,k+1,shipAmount)) {return true;}
shipAmount[SizePlacement[k]-2]++;
}
}
if(board[row][col]==1 && col+SizePlacement[k]<board[0].length) {//horizontally
cnt=1;
for(int i=1;i<SizePlacement[k];i++) {//check horizontally
if(board[row][col+i]==1) {cnt++;}
}
if(cnt>=SizePlacement[k]) {
int[][] newBoard = deepcopy(board);
newBoard= remove(newBoard , row, col, SizePlacement[k], "hor");
shipAmount[SizePlacement[k]-2]--;
if(shipAmount==new int[]{0,0,0}) {return true;}
if(k+1<SizePlacement.length &&checkBoard(newBoard,SizePlacement,k+1,shipAmount)) {
return true;
}
shipAmount[SizePlacement[k]-2]++;
}
}
}
}
return false;
}
public static int[][] remove(int[][] newBoard,int row,int col,int size,String orien){
int[][] removedBoard= deepcopy(newBoard);
if(orien=="ver") {
for(int i=0;i<size;i++) {
removedBoard[row+i][col]=0;
}
print(removedBoard);
return removedBoard;
}
else if(orien=="hor") {
for(int i=0;i<size;i++) {
removedBoard[row][col+i]=0;
}
print(removedBoard);
return removedBoard;
}
return removedBoard;
}
public static int[][] deepcopy(int[][] fields){
int[][] copy= new int[fields.length][fields[0].length];
for (int row = 0; row < fields.length; row++) {
for (int col = 0; col < fields[0].length; col++) {
copy[row][col]= fields[row][col];
}
}
return copy;
}
public static int counter(int[][] f) {// counts amount of tiles on the board with 1's
int cnt=0;
for (int col = 0; col < f[0].length; col++) {
for (int row = 0; row < f.length; row++) {
if (f[row][col] == 1) {
cnt++;
}
}
}
return cnt;
}
public static void print(int[][] field) {//prints the board
for (int row = 0; row < field.length; row++) {
for (int col = 0; col < field[0].length; col++) {
if(col<field[0].length-1 && col!=0) {
System.out.print( field[row][col]+",");
}
else if(col==field[0].length-1){
System.out.print( field[row][col]+"},");
}
else if(col==0) {
System.out.print(" {"+ field[row][col]+",");
}
}
System.out.println("");
}
System.out.println("\n");
}
}
这似乎有一些程序上的错误(不同于解决方案),不确定是否需要帮助。[1]: https://istack.dev59.com/bX32n.webp [2]: https://istack.dev59.com/tFP1N.webp