"Minesweeper" 在 C 中,计算周围地雷在棋盘中某个位置附近的问题

"Minesweeper" in C, trouble on counting surrounding mines are near a certain spot in the board

我必须用 C 重新创建游戏的简单版本 "Minefield",但我无法计算棋盘上某个位置附近有多少地雷。我的一段代码遍及整个阵列(板)搜索地雷。当它找到地雷时,它应该在地雷周围的所有地点加起来+1。我的代码只适用于 T[0][0] 周围的点。 m 和 n 代表板上的行数和列数。请帮忙!!

void mine_counting (int T[MMAX][NMAX], int m, int n)
{
int cont, i, j;

for (i = 0 ; i < m ; i++)
{
    printf("\ni = %d", i);
    for (j = 0 ; j < n ; j++)
        printf("\nj = %d", j);
        {
        if (T[i][j] == -3)
            {
            if (i == 0)
                {
                printf("i=0");
                if (j == 0)
                    {
                    if (T[i][j+1] != -3)
                        T[i][j+1] = T[i][j+1] + 1;
                    if (T[i+1][j] != -3)
                        T[i+1][j] = T[i+1][j] + 1;
                    if (T[i+1][j+1] != -3)
                        T[i+1][j+1] = T[i+1][j+1] + 1;
                    }
                if (j == (n-1))
                    {
                    printf("j = n-1");
                    if (T[i][j-1] != -3)
                        T[i][j-1] = T[i][j-1] + 1;
                    if (T[i+1][j] != -3)
                        T[i+1][j] = T[i+1][j] + 1;
                    if (T[i+1][j-1] != -3)
                        T[i+1][j-1] = T[i+1][j-1] + 1;
                    }
                if (j != 0 && j!= (n-1))
                    {
                    if (T[i+1][j] != -3)
                        T[i+1][j] = T[i+1][j] + 1;
                    if (T[i+1][j+1] != -3)
                        T[i+1][j+1] = T[i+1][j+1] + 1;
                    if (T[i+1][j-1] != -3)
                        T[i+1][j-1] = T[i+1][j-1] + 1;
                    if (T[i][j+1] != -3)
                        T[i][j+1] = T[i][j+1] + 1;
                    if (T[i][j-1] != -3)
                        T[i][j-1] = T[i][j-1] + 1;
                    }
                }
            if (i == (m-1))
                {
                if (j == 0)
                    {
                    if (T[i][j+1] != -3)
                        T[i][j+1] = T[i][j+1] + 1;
                    if (T[i-1][j] != -3)
                        T[i-1][j] = T[i-1][j] + 1;
                    if (T[i-1][j+1] != -3)
                        T[i-1][j+1] = T[i-1][j+1] + 1;
                    }
                if (j == (n-1))
                    {
                    if (T[i-1][j] != -3)
                        T[i-1][j] = T[i-1][j] + 1;
                    if (T[i-1][j-1] != -3)
                        T[i-1][j-1] = T[i-1][j-1] + 1;
                    if (T[i][j-1] != -3)
                        T[i][j-1] = T[i][j-1] + 1;
                    }

                if (j != 0 && j!= (n-1))
                    {
                    if (T[i-1][j] != -3)
                        T[i-1][j] = T[i-1][j] + 1;
                    if (T[i-1][j+1] != -3)
                        T[i-1][j+1] = T[i-1][j+1] + 1;
                    if (T[i-1][j-1] != -3)
                        T[i-1][j-1] = T[i-1][j-1] + 1;
                    if (T[i][j+1] != -3)
                        T[i][j+1] = T[i][j+1] + 1;
                    if (T[i][j-1] != -3)
                        T[i][j-1] = T[i][j-1] + 1;
                    }
                }
            if (j == 0 && i != 0 && i!= (m-1))
                {
                if (T[i-1][j] != -3)
                    T[i-1][j] = T[i-1][j] + 1;
                if (T[i-1][j+1] != -3)
                    T[i-1][j+1] = T[i-1][j+1] + 1;
                if (T[i][j+1] != -3)
                    T[i][j+1] = T[i][j+1] + 1;
                if (T[i+1][j+1] != -3)
                    T[i+1][j+1] = T[i+1][j+1] + 1;
                if (T[i+1][j] != -3)
                    T[i+1][j] = T[i+1][j] + 1;
                }
            if (j == (n-1) && i != 0 && i!= (m-1))
                {
                if (T[i-1][j] != -3)
                    T[i-1][j] = T[i-1][j] + 1;
                if (T[i-1][j-1] != -3)
                    T[i-1][j-1] = T[i-1][j-1] + 1;
                if (T[i][j-1] != -3)
                    T[i][j-1] = T[i][j-1] + 1;
                if (T[i+1][j-1] != -3)
                    T[i+1][j-1] = T[i+1][j-1] + 1;
                if (T[i+1][j] != -3)
                    T[i+1][j] = T[i+1][j] + 1;
                }
            if ((i != 0) && (i != (m-1)) && (j != 0) && (j != (n-1)))
                {
                if (T[i-1][j] != -3)
                    T[i-1][j] = T[i-1][j] + 1;
                if (T[i-1][j-1] != -3)
                    T[i-1][j-1] = T[i-1][j-1] + 1;
                if (T[i][j-1] != -3)
                    T[i][j-1] = T[i][j-1] + 1;
                if (T[i+1][j-1] != -3)
                    T[i+1][j-1] = T[i+1][j-1] + 1;
                if (T[i+1][j] != -3)
                    T[i+1][j] = T[i+1][j] + 1;
                if (T[i+1][j+1] != -3)
                    T[i+1][j+1] = T[i+1][j+1] + 1;
                if (T[i][j+1] != -3)
                    T[i][j+1] = T[i][j+1] + 1;
                if (T[i-1][j+1] != -3)
                    T[i-1][j+1] = T[i-1][j+1] + 1;
                }

您的方法可能会被固定下来工作,但它已经产生了太多的代码行。

首先,包含地雷和邻接计数的数据结构有点做作。它确实代表了可见板,但是它将两种不同类型的信息塞进了 int 数据类型。

其次,列出相邻点不如使用循环自动查找它们优雅。边缘有特殊情况(文字边缘情况!),但您可以通过用零填充它们来避免这种情况。

所以,例如,

// Parameter "mines" is the minefield, plus a ring of zero values around the edge.
// Parameter "adjacence" must be pre-filled with zeroes. It has no such padding.
void mine_counting (const bool mines[MMAX+2][NMAX+2], int adjacence[MMAX][NMAX],
                    int m, int n) {
    for ( int di = -1; di <= 1; ++ di ) {
        for ( int dj = -1; dj <= 1; ++ dj ) {
            for ( int i = 0; i != m; ++ i ) {
                for ( int j = 0; j != n; ++ j ) {
                    adjacence[i][j] += mines[i + di + 1][j + dj + 1];
                }
            }
        }
    }
}

如果你想让两个数组的坐标系完全匹配,你可以在adjacence中添加相同的填充——这不会有什么坏处。然后最里面的循环中的+1就会消失。

你真的让它变得比实际更复杂..

为什么不使用循环?它们是为完成这些工作而生的。将任务分解成更小的函数可以使编码变得更容易和更快。它还将使您的代码更易于阅读和维护。

[edit] 我添加了通用的 min 和 max 宏,它们是每个 C 程序员工具箱中必备的。感谢@bolov 的建议。

#define MINE (-3)

// lower-case min, max are defined in <windows.h>, hence the choice 
// and the check.

#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif

int mine_detector(int board[M][N], int x, int y)
{
  int result, i, j, xmin, xmax, ymin, ymax;

  xmin = min(x - 1, 0);    // compute your boundaries beforehand
  xmax = max(x + 1, M - 1);
  ymin = min(y - 1, 0);
  ymax = max(y + 1, N - 1);

  if (board[x][y] == MINE)
    return MINE;

  result = 0;

  for (i = xmin; i <= xmax; ++i)
    for (j = ymin; j <= ymax; ++j)
      if (board[i][j] == MINE)
        ++result;

  return result;
}

void count_mines(int board[M][N])
{
  // returns detected mines on board[][] in board[][]
  int i, j;
  for (i = 0; i < M; ++i)
    for (j = 0; j < N; ++i)
       board[i][j] = mine_detector(board, i, j);
}