棋盘游戏中的递归矿爆炸功能

时间:2016-05-23 18:42:45

标签: c++ recursion

我正在尝试在C ++上实现一个棋盘游戏,它的一些功能如下:

  • 我有4个来源,名为Mine(M),Water(W),Food(F)和Medical Supplies(S)

  • 来源将随机分配给董事会(我已完成)

  • 用户将输入两个坐标,如果这些坐标上有我的坐标,他们将根据它们的位置炸毁并摧毁周围的细胞。例如,如果矿井位于中间的某个地方,它将摧毁它周围的8个单元,如果另一个矿井周围有另一个矿井爆炸,它将使另一个矿井爆炸。

  • 还有一些例外情况,例如,如果坐标位于拐角处,它只会炸掉3个单元格。

让我们来解决真正的问题。当我尝试实现它时,我看到它实际上是大量的代码,我需要使其递归以提供炸毁其他单元的能力,因此对于每一个可能性我需要检查吹制的单元是否是我的。有没有一种有效的方法来实现它,还是我需要编写整个代码?

    void explode_mines(int x,int y) {
        if (x == 0 && y == 0) {
            grid[0][0] = 'X';
            grid[0][1] = 'X';
            if (grid[0][1] == 'X') explode_mines(0, 1);
            grid[1][0] = 'X';
            //...
            grid[1][1] = 'X';
            //...
    }
    //Is there any efficient way?

3 个答案:

答案 0 :(得分:7)

伪代码:

void ExploreCell(int x, int y)
{
    if (x or y are out of bounds (less than zero/greater than max))
       or (this cell is a mountain, because mountains don't explode))
        return
    else if this location is a mine
        ExplodeMine(x, y) //This cell is a mine, so it blows up again
    else
        DestroyCell(x, y) //This cell is a valid, non-mine target
}

void ExplodeMine(int x, int y)
{
    ExploreCell(x-1, y-1);
    ExploreCell(x-1, y);
    ....
    ExploreCell(x+1, y+1);
}

void DestroyCell(int x, int y)
{
      //Take care of business
}

答案 1 :(得分:0)

我认为您的代码中存在拼写错误:

        grid[0][1] = 'X';
        if (grid[0][1] == 'X') explode_mines(0, 1);

位置(0,1)不是将如何' X"在这一点?

没有递归,但信息理论确实说你必须进行8次检查。但可以使其更具可读性。出于一般目的,我发现基本外围检查是可维护的。在这里,我会让" O"是一个陨石坑"" M"是一个矿井。

grid[x][y] = ' '
for (row = x-1; row <= x+1; row++) {
    for (col = x-1; col <= x+1; col++) {
        if grid[row][col] == "M"
            explode_mines(row, col)
    }
}

现在,如果你必须担心巨大的连锁反应花费的时间,那么你可以改变你的算法以保留两个列表:

  • 需要检查的正方形
  • 与地雷爆炸的方块

在这种情况下, explode_mines 看起来更像是这样:

Mark x,y as a dead square
Add adjacent squares to the checking list; do *not* add a duplicate

...你得到一个新的例程 check_for_mine ,如下所示:

while check list is not empty {
  while mine list is not empty {
    explode the top mine on the list
  }
  take the top square from the check list and check it
}

您可以使用嵌套,具体取决于您喜欢的连锁反应顺序。对于广度优先爆炸,你检查核对清单上的所有方块,然后爆炸矿井清单上的所有矿井;重复一遍,直到两个列表都为空。对于深度优先,您可以稍微简化循环:一旦找到它就会爆炸每个矿井,这意味着您根本不需要矿山列表。

答案 2 :(得分:0)

希望这有助于[警告:未经测试]('d'代表“毁灭”,'b'代表“炸弹”)

void destroy (int x, int y)
 {
   char  oldVal;

   if (    (x >= 0) && (x < maxX) && (y >= 0) && (y < maxY)
        && ('d' != (oldVal = grid[x][y])) ) // 'd' for destroyed
    {
      grid[x][y] = 'd';  // set "destroyed"

      if ( 'b' == oldVal ) // if it was a bomb, destroy surrounding
       {
         destroy(x-1, y-1);
         destroy(x-1, y);
         destroy(x-1, y+1);
         destroy(x,   y-1);
         destroy(x,   y+1);
         destroy(x+1, y-1);
         destroy(x+1, y);
         destroy(x+1, y+1);
       }
    }
 }