되는대로 살자

[C언어 기출문제&풀이] 그래픽 편집기(Graphical Editor) 본문

2009~2014/C/C++

[C언어 기출문제&풀이] 그래픽 편집기(Graphical Editor)

malu 2011. 5. 13. 22:58

문제:포토샵 같은 그래픽 편집기를 이용하면 텍스트 편집기에서 문서를 수정하는 것처럼 비트맵 이미지를 수정할 수 있다. 이미지는 픽셀로 이루어진 MXN배열로 표현되며 각 픽셀마다 색이 주어진다.

간단한 대화형 그래픽 편집기 흉내를 낼 수 있는 프로그램을 만들어 보자.

입력:입력은 한 줄에 하나씩의 편집기 명령으로 구성된다. 각 명령은 줄 맨 앞에 있는 대문자 한 개로 표현된다. 매개변수가 필요한 경우에는 그 명령과 같은 줄에 스페이스로 분리되어 매개변수가 입력된다.

픽셀 좌표는 1이상 M이하의 열 번호와 1이상 N이하의 행 번호, 이렇게 두 개의 정수로 표현되며 이때 1<=M,N<=250라는 조건이 만족된다. 표의 왼쪽 위 꼭지점을 원점으로 삼는다. 색은 대문자로 지정된다. 편집기에서 받아들이는 명령은 다음과 같다.

I M N :모든 픽셀이 흰색(O)으로 칠해진MXN 이미지를 새로 만든다.
C: 모든 픽샐을 흰색(O)으로 칠해서 표를 지운다. 이미지의 크기는 바뀌지 않는다.
L X Y C : (X,Y)픽셀을 주어진 색(C)으로 칠한다.
V X Y1 Y2 C : X열에 Y1 행과 Y2행(Y1,Y2포함)사이에 주어진 색(C)으로 수직 방향 직선을 긋는다.
H X1 X2 Y C : Y행에 X1 열과 X2행 (X1,X2 포함) 사이에 주어진 색(C)으로 수평 방향 직선을 긋는다.
K X1 Y1 X2 Y2 C : 주어진 색(C)으로 채워진 직사각형을 그린다. (X1,Y1)은 왼쪽 위 끝점, (X2,Y2)는 오른쪽 아래 끝 점을 의미한다.
F X Y C : R 영역을 주어진 색(C)으로 채우는데, 영역 R은 다음과 같이 정의된다. (X,Y)픽셀과 색이 같고 R에 포함된 픽셀과 맞닿은 부분이 하나라도 있다면 그 픽셀도 R 영역에 포함된다.
S Name : 파일명은 MSDOS 8.3 형식으로 출력하고 그 뒤에 현재 이미지의 내용을 출력한다.
X: 세션을 종료한다.

출력 : S NAME이라는 명령이 있을 때마다 NAME으로 주어진 파일명을 출력하고 현재 이미지의 내용을 출력한다. 각 행은 각 픽셀의 색을 나타내는 문자로 표시된다. 출력 예를 참고하자. I,C,L,V,H,K,F,S,X를 제외한 문자로 정의된 명령이 있으면 그 줄 전체를 무시하고 다음 명령으로 넘어간다. 다른 오류에 대해서는 프로그램의 행동을 예측할 수 없다.

풀이:이 문제는 내가 뿌요뿌요 프로그램을 만들때의 알고리즘과 많이 비슷하기 때문에 예로 인용하도록 하겠다. 이런 X,Y를 사용하는 배열에서 자주하는 실수는 map[y][x]라고 쓰지 않고, map[x][y]라고 쓰는 것이다. 나도 테트리스와 뿌요뿌요를 분석하며 프로그램을 만들 때 디버깅 하면서 가장 멍청했다고 생각한 것이 map[y][x]를 잘못 표기한 것이다. 그리고 왠만한 것은 문제의 조건에 따라 코딩만 잘 하면 된다. 그나마 특별하다고 할 수 있는 것은 F명령인데 이 부분은 상하좌우에 같은 색이 있는지를 판별하고 같은 색이면 자기호출(재귀)을 한다.
아, 그리고 이 문제와 상관없는 일이지만 이 문제를 풀면서 생긴 일이라 적는다. 참고로 지역변수와 같은 이름으로 전역변수를 선언하지 말자..
소스코드 :
#include <stdio.h>

static char bitmap[100][100],color;
static int m=0,n=0;

void Fill(int,int,char,char);


void Fill(int i, int j,char old_c,char color)
{
 bitmap[i][j]=color;

 if(i > 1 && bitmap[i-1][j] == old_c)
  Fill(i-1,j,old_c,color);
 if(i < n && bitmap[i+1][j] == old_c)
  Fill(i+1,j,old_c,color);
 if(j > 1 && bitmap[i][j-1] == old_c)
  Fill(i,j-1,old_c,color);
 if(j < m && bitmap[i][j+1] == old_c)
  Fill(i,j+1,old_c,color);
}

int main()
{
 int i,j,i1,i2,j1,j2,temp;
 char color,command='\0',name[20];
 while(command != 'X')
 {
  scanf("%c",&command);
  switch(command)
  {
  case 'I':
   scanf("%d%d",&m,&n);
   for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
     bitmap[i][j]='O';
   break;
  case 'C':
   for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
     bitmap[i][j]='O';
   break;

  case 'L':
   scanf("%d %d %c",&j,&i,&color);
   bitmap[i][j]=color;
   break;

  case 'V':
   scanf("%d %d %d %c",&j,&i1,&i2,&color);
   if(i1>i2)
   {
    temp = i1;
    i1=i2;
    i2=temp;
   }
   for(i=i1;i<=i2;i++)
    bitmap[i][j]=color;
   break;

  case 'H':
   scanf("%d %d %d %c",&j1,&j2,&i,&color);
   if(j1 > j2)
   {
    temp=j1;
    j1=j2;
    j2=temp;
   }
   for(j=j1;j<=j2;j++)
    bitmap[i][j]=color;
   break;

  case 'K':
   scanf("%d %d %d %d %c",&j1,&i1,&j2,&i2,&color);
   for(i=i1;i<=i2;i++)
    for(j=j1;j<=j2;j++)
     bitmap[j][i]=color;
   break;
  case 'F':
   scanf("%d %d %c",&j,&i, &color);
   Fill(i,j,bitmap[i][j],color);
   break;

  case 'S':
   scanf("%s",&name);
   printf("%s\n",name);
   for(i=1;i<=n;i++) {
    for(j=1;j<=m;j++)
     putchar(bitmap[i][j]);
    putchar('\n');
   }
   break;
  }
 }
}