이번 포스팅은 ‘C언어 코딩도장’의 <Unit 38 포인터와 배열 응용하기>에 나와있는 지뢰찾기 문제의 답입니다.

문제


표준 입력으로 행렬의 크기 m, n과 문자(char) 행렬이 입력됩니다(m과 n의 범위는 3~10). 입력된 m, n은 공백으로 구분되며 행렬 안에서 *은 지뢰이고 .은 지뢰가 아닙니다. 지뢰가 아닌 요소에는 인접한 지뢰의 개수를 출력하는 프로그램을 만드세요(scanf 함수 호출 전에 문자열을 출력하면 안 됩니다).

여러 줄을 입력 받으려면 다음과 같이 for 반복문으로 scanf를 반복 호출하면 됩니다.

for (int i = 0; i < m; i++)
{
    scanf("%s", matrix[i]);
}

행렬의 가로 공간에는 문자열이 들어갑니다. 따라서 메모리를 할당할 때는 n + 1(가로 크기 + 1)만큼 할당하여 NULL이 들어갈 공간까지 확보해야 합니다.


예)

입력
5 5
* . . . .
. * . * *
. * . . .
. . . . .
. . . . .


출력

* 2 2 2 2
3 * 3 * *
2 * 3 2 2
1 1 1 0 0
0 0 0 0 0



코드


#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(){
    int m, n;                
    int mine_counter = 0;                                                       // 주변 지뢰 카운터
    int i, j;

    scanf("%d %d", &m, &n);                                                     // 행렬의 크기 입력

    char **minesweeper = malloc(sizeof(char *) * m);                            // 행렬의 세로(가로줄) 할당

    for(i = 0; i < m; i++){                                                     // 세로 크기만큼 반복
        minesweeper[i] = malloc(sizeof(char) * (n + 1));                        // 가로 크기만큼 반복
        memset(minesweeper[i], 0, sizeof(char) * (n + 1));                      // 각 요소를 0으로 초기화
    }

    for(i = 0; i < m; i++){                                                     // 문자열 입력
        scanf("%s", minesweeper[i]);
    }

    for(i = 0; i < m; i++){                                                     // 배열의 요소를 검색 후 '*' 와 같으면 넘어감
        for(j = 0; j < n; j++){
            if(minesweeper[i][j] == '*'){
                printf("%c", minesweeper[i][j]);
                continue;
            }

            else{                                                               // '*'와 같지 않으면 현재 위치 주변 8개
                for(int y = i - 1; y <= i + 1; y++){                            // (왼쪽 위 대각선, 위, 오른쪽 위 대각선,
                    for(int x = j - 1; x <= j + 1; x++){                        //  왼쪽, 오른쪽
                        if(y < 0 || x < 0 || y >= m || x >= n) continue;        //  왼쪽 아래 대각선, 아래, 오른쪽 아래 대각선)
                        else if(minesweeper[y][x] == '*') mine_counter += 1;    // 범위를 벗어나면 넘어가고, 검색했을때 '*'와 같다면 mine_counter에 1씩 추가
                    }
                }
                minesweeper[i][j] = mine_counter;                               // 해당 위치에 지뢰 갯수 표시 후 mine_counter는 0으로 초기화
                printf("%d", minesweeper[i][j]);
                mine_counter = 0;
            }
        }
        printf("\n");
    }

    for(int i = 0; i < m; i++){                                                 // 할당한 메모리 해제
        free(minesweeper[i]);
    }

    free(minesweeper);

    return 0;
}


아직 많이 부족한 부분이라 많이 부끄럽지만 혹시나 도움이 필요하신 분이 계실까 공유합니다!
조언이나 틀린부분 지적 환영합니다 :)