되는대로 살자

[C언어 기출문제&풀이] 지뢰찾기(minesweeper) 본문

2009~2014/C/C++

[C언어 기출문제&풀이] 지뢰찾기(minesweeper)

malu 2011. 5. 13. 18:37

문제: 지뢰 찾기를 해본 적이 있는 사람들이 많을 것이다. 이름은 잘 기억나지 않지만 어떤 운영체제에 이 작고 귀여운 게임이 깔려있다. 기뢰찾기는 M*N 크기의 지뢰밭에서 모든 지뢰의 위치를 찾아내는 게임이다.

이 게임에서는 각 칸에 인접한 칸에 몇 개의 지뢰가 있는지를 보여준다. 각 칸에는 최대 여덟 개의 인접한 칸이 있을 수 있다. 아래에서 왼쪽에 있는 4*4 지뢰밭에는 지뢰 두 개가 있으며 각각은 '*' 문자로 표시되어 있다. 이 지뢰밭을 방금 설명한 힌트 숫자로 표기하면 오른 쪽에 있는 것과 같은 필드가 만들어 진다.

*...    *100
....    2210
.*..    1*10
....    1110
입력:입력은 임의 개수의 지뢰밭으로 구성된다. 각 지뢰밭의 첫번째 줄에는 각각 행과 열의 개수를 나타내는 두 개의 정수 n과 m(0<n,m<=100)이 들어있다. 그 ㄷ다음 줄부터는 n개의 줄에 걸쳐서 각 줄마다 정확하게 m개 씩의 문자가 들어있으며 이는 지뢰밭을 나타낸다. 그 다음 줄부터는 n개의 줄에 걸쳐서 '.'
지뢰가 없는 칸은 ','으로, 지뢰는 '*'로 표시되며 이때 따옴표는 쓰지 않는다. n=m=0인 줄은 입력이 끝났음을 나타내는 것이므로 그 줄은 처리하지 않는다.

출력:각 지뢰밭에 대해 Field #x:라고 적혀있는 메시지를 출력한다. 이때 x는 필드 번호를 나타내며 1에서 시작한다. 그 다음 줄부터는 n rodml wnfdp rjfcutj ','문자 대신 그 칸에 인접한 칸에 들어있는 지뢰의 개수를 출력한다. 각 지뢰밭에 대한 출력 사이에는 반드시 빈 줄이 하나씩 있어야 한다.

풀이:전에 지뢰찾기 프로그램을 구현해 본적이 있어서 아주 쉽게 풀었다. 지뢰찾기에서 이것보다 구현하기가 까다로운 것은 빈칸이 나왔을 때 주변의 인접한 빈칸을 모두 출력하는 것이다. 상대적으로 까다로운 것이지 그리 까다롭지도 않으니 시간을 내어 그것도 구현해보길 바란다.
아 그리고 여기서 중요한 것은 루프에서 i,j,가 1부터 시작한다는 것이다. 0부터 돌지 않는 이유는 만약 x 좌표에 지뢰가 있는 것은 배열 첨자가 음수가 되어버려서 오버플로우가 발생하기 때문이다.

소스코드 :
#include <stdio.h>

#define MAX_M 10
#define MAX_N 10
int main()
{
 int n,m,i,j,i2,j2,field_id; //x,y,배열 순회,filed_id는 n번째 지뢰판을 나타냄
 char row[MAX_M+1];
 char mf[MAX_N+2][MAX_M+2]; // 출력할 것
 scanf("%d",&m,&n);
 field_id =1;
 scanf("%d %d",&n,&m);
 while(n || m)
 {
  //초기화
  for(i=1;i<=n;i++)
   for(j=1;j<=m;j++)
    mf[i][j]='0';

   for(i=1;i<=n;i++)
   {
    scanf("%s",row);
    for(j=1;j<=m;j++)
     if(row[j-1]=='*')
     {
      for(i2=i-1;i2<=i+1;i2++)
       for(j2=j-1;j2<=j+1;j2++)
        if(mf[i2][j2] !='*')
         mf[i2][j2]++;
       mf[i][j]='*';
     }
   }
   if(field_id>1) printf("\n");
   printf("Filed #%d:\n",field_id++);
   for(i=1;i<=n;i++)
   {
    for(j=1;j<=m;j++)
     putchar(mf[i][j]);
    putchar('\n');
   }
   scanf("%d %d",&n,&m);
 }
}