计数可用块的算法,直到有可用块为止

时间:2019-02-08 17:03:37

标签: java arrays algorithm

对于长度为(x,y)的字段(例如9x6),它存在一个二维数组。我需要在这里检查橙色和红色星星周围有多少个空闲字段。黑色(实心)字段表示已占用的字段。例如,在此示例中,我有7个用于橙色的自由字段,1个用于红色的字段。我知道我可以遍历每个字段并查看是否有一个字段被占用,但是我该如何遍历,以便知道这些未占用的字段位于恒星旁边或非恒星的半径中占领领域?我希望我能很好地阐述我的问题。

Screenshot of Example

Field[][] fields = new Field[9][6];

private void checkEmptyFields(Star star) {
for (int i = 0; i < 9; i++){ // Hardcoded size as an example
 for (int j = 0; i < 6; i++) {
   if(fields[i][j].isOccupied())
    { 
     //It is occupied, but what now?
    }
  }
 }
}

isOccupied函数:

public boolean isOccupied(){
return occupied;
}

在此示例中,我希望输出为橙色:7,红色:1(因为红色被橙色星号和占用的方块遮挡了)

1 个答案:

答案 0 :(得分:3)

这似乎是一个问题,其中广度优先搜索是在此处使用的合适算法。广度优先搜索(BFS)是您访问节点的所有邻居(在本例中为字段)时首先访问的邻居。在您的情况下,“访问”仅表示检查是否已被占用。如果它的相邻字段未被占用并且以前没有被访问过,那么您可以搜索该字段及其邻居。搜索顺序是通过使用类似Queue的数据结构来确定的,

private void checkEmptyFields(Star star) {
    boolean visited[9][6] = new visited[9][6];
    //get the star's coordinates somehow, you may have to change this
    int i = star.row;
    int j = star.col;
    visited[i][j] = true;

    int freeFieldCount = 0;
    Queue<Field> q = new LinkedList<Field>();
    q.add(fields[i][j]);

    while(!q.isEmpty()) {
         Field current = q.poll();
         //get the coordinates from the field, you may have to change this
         i = current.row;
         j = current.col;
         int rowUpperLimit = i + 1;
         int rowLowerLimit = i - 1;
         int colUpperLimit = j + 1;
         int colLowerLimit = j - 1;
         if(rowUpperLimit >= 9) {
              rowUpperLimit = 8;
         }
         if(rowLowerLimit < 0) {
              rowLowerLimit = 0;
         }
         if(colUpperLimit >= 6) {
              colUpperLimit = 5;
         }
         if(colLowerLimit < 0) {
              colUpperLimit = 0;
         }
         //check immediate neighbors
         for(int m = rowLowerLimit; m <= rowUpperLimit; m++) {
             for(int n = colLowerLimit; n <= colUpperLimit; n++) {
                 if((m != i && n != j) && !visited[m][n] && !fields[m][n].isOccupied()) {
                     freeFieldCount++;
                     visited[m][n] = true;
                     q.add(fields[m][n]);
                 }
             }
         }
    }

    return freeFieldCount;
}

正如@juvian用户提到的那样,这是一种8邻居方法。如果要执行4邻居方法,只需仅访问当前字段左侧,右侧,上方或下方的邻居即可。您可以像这样修改while循环,

while(!q.isEmpty()) {
         Field current = q.poll();
         //get the coordinates from the field, you may have to change this
         i = current.row;
         j = current.col;
         int rowUpperLimit = i + 1;
         int rowLowerLimit = i - 1;
         int colUpperLimit = j + 1;
         int colLowerLimit = j - 1;
         if(colLowerLimit > -1) {
             //check neighbor to the left
             if(!visited[i][colLowerLimit] && !fields[i][colLowerLimit].isOccupied()) {
                 freeFieldCount++;
                 visited[i][colLowerLimit] = true;
                 q.add(fields[i][colLowerLimit]);
             }
         }
         if(colUpperLimit < 6) {
             //check neighbor to the right
             if(!visited[i][colUpperLimit] && !fields[i][colUpperLimit].isOccupied()) {
                 freeFieldCount++;
                 visited[i][colUpperLimit] = true;
                 q.add(fields[i][colUpperLimit]);
             }
         }
         if(rowLowerLimit > -1) {
             //check neighbor below
             if(!visited[rowLowerLimit][j] && !fields[rowLowerLimit][j].isOccupied()) {
                 freeFieldCount++;
                 visited[rowLowerLimit][j] = true;
                 q.add(fields[rowLowerLimit][j]);
             }
         }
         if(rowUpperLimit < 9) {
             //check neighbor above
             if(!visited[rowUpperLimit][j] && !fields[rowUpperLimit][j].isOccupied()) {
                 freeFieldCount++;
                 visited[rowUpperLimit][j] = true;
                 q.add(fields[rowUpperLimit][j]);
             }
         }
    }
}