출처 : 반크_백제역사 유적지구 및 이스탐블역사 유적지구
문제]
포토샵 같은 그래픽 편집기를 이용하면 텍스트 편집기에서 문서를 수정하는 것처럼 비트맵 이미지를 수정할 수 있다. 이미지는 픽셀로 이루어진 M × N 배열로 표현되며 각 픽셀마다 색이 주어진다. 간단한 대화형 그래픽 편집기 흉내를 낼 수 있는 프로그램을 만들어보자.
입력
입력은 한 줄에 하나씩의 편집기 명령으로 구성된다. 각 명령은 줄 맨 앞에 잇는 대문자 한 개로 표현된다. 매개변수가 필요한 경우에는 그 명령과 같은 줄에 스페이스로 분리되어 매개변수가 입력된다.
픽셀 좌표는 1 이상 M 이하의 열 번호와 1 이상 N 이하의 행 번호, 이렇게 두 개의 정수로 푠현되며 이때 1<=M, N<=250라는 조건이 만족된다. 표의 왼쪽 위 꼭지점을 원점으로 삼는다. 색은 대문자로 지정된다.
편집기에서 받아륻이는 명령은 다음과 같다.
I M N | 모든 픽셀이 흰색(O)으로 필해진 M × N 이미지를 새로 만든다. |
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행과 V2행(X1, X2 포함) 사이에 주어진 색(C)으로 수평 방향 직선을 긋는다. |
K X1 Y1 X2 Y2 C | 주어진 색(C)으로 채워진 직사각형을 그린다. (X1, Y1)은 왼쪽 위 끝점. (X2, Y2)은 오른쪽 아래 끝점 의미 |
F X Y C | R영역을 주어진 색(C)으로 채우는데, 영역 R은 다음과 같이 정의된다. (X, Y) 픽셀은R에 속한다. (X, Y)픽셀과 색이 같고 R에 포합된 픽셀과 맞닿은 부분이 하나라도 있다면 그 빅셀도 R 영역에 포함된다. |
S Name | 파일명을 MSDOS 8.3형식으로 출력하고 그 뒤에 현재 이미지의 내용을 출력한다. |
X | 세션을 종료한다. |
출력
S NAMW이라는 명령이 있으 때마다 NAME으로 주어진 파일명을 출력하고 현재 이미지의 내용을 출력한다. 각 행은 각 픽셀의 색을 나타내는 문자로 표시된다. 출력 예를 참고하자.
I, C, L, V, H, K, F, S, X를 제외한 문자로 정의된 명령이 있으면 그 줄 전체를 무시하고 다음 명령으로 넘어간다. 다른 오류에 대해서는 프로그램의 행동을 예측할 수 없다.
입력 예
I 5 6
L 2 3 A
S one.bmp
G 2 3 J
F 3 3 J
V 2 3 4 W
H 3 4 2 Z
S two.bmp
X
츨력 예
one.bmp
OOOOO
OOOOO
OAOOO
OOOOO
OOOOO
OOOOO
two.bmp
JJJJJ
JJZZJ
JWJJJ
JWJJJ
JJJJJ
JJJJJ
출처]
Programming Challenges 알고리즘 트레이닝 북(한빛미디어) : 문제 5 그래픽 편집기(Graphical Editor) p44
참고풀이]
#include <stdio.h>
#include <string.h> //strlen(), strcpy(), strcmp()
#include <stdlib.h> //atoi()
#include <ctype.h> //toupper()
static char bitMap[251][251];
static int M=0, N=0;//픽셀좌표 열, 행 변수
struct Division{
char dCom;
int m1;
int m2;
int m3;
int m4;
char dColor;
char dName[20];
} D;
void Swap(int *x, int *y)
{
int t;
t=*x;
*x=*y;
*y=t;
}
void DiChk(char *cStr,int n)
{
if(n==0) {
if(toupper(cStr[0])>='A' && toupper(cStr[0])<='Z') strcpy(D.dName,cStr);
else D.m1=atoi(cStr);
}
else if(n==1) { D.m2=atoi(cStr); n++; }
else if(n==2) {
if(toupper(cStr[0])>='A' && toupper(cStr[0])<='Z') D.dColor=cStr[0];
else D.m3=atoi(cStr);
}
else if(n==3) {
if(toupper(cStr[0])>='A' && toupper(cStr[0])<='Z') D.dColor=cStr[0];
else D.m4=atoi(cStr);
}
else
D.dColor=cStr[0];
}
//입력된 문자열을 명령어 등등으로 나눈다.
void Division(char *Str)
{
int i, j, k, n;
char Chk[20]={'\0'};//각 구분 문자열 변수
D.m1=0;
D.m2=0;
D.m3=0;
D.m4=0;
D.dColor='O';
strcpy( D.dName,"");
D.dCom=toupper(Str[0]);
for(n=0,k=0,j=2;j<strlen(Str);j++)
if(Str[j] != ' ')
Chk[k++]=Str[j];
else
{
Chk[k]='\0';
DiChk(Chk,n);
k=0;
n++;
}
if(Str[strlen(Str)-1] != ' ')
{
Chk[k]='\0';
DiChk(Chk,n);
}
}
//(i,j)위치에서 시작하여 color를 칠한다.
void Fill(int i, int j, char org, char color)
{
bitMap[i][j]=color;
if(i>1 && bitMap[i-1][j]==org) //위
Fill(i-1, j, org, color);
if(i<N && bitMap[i+1][j]==org) //아래
Fill(i+1, j, org, color);
if(j>1 && bitMap[i][j-1]==org) //좌측
Fill(i, j-1, org, color);
if(i<M && bitMap[i][j+1]==org) //우측
Fill(i, j+1, org, color);
}
int main()
{
int i, n;
int r, rs, re;//행, 행시작, 행끝 변수
int c, cs, ce;//열, 열시작, 열끝 변수
char inStr[100][20]={'\0'};
char com;//입력되는 명령어 변수
char color;//색변수
char fileName[13]={'\0'};//파일명 변수
//자료를 입력받는다.
n=0;
while(1)
{
gets(inStr[n]);
if(strcmp(inStr[n],"X")==0) break;
n++;
}
//입력 명령어를 기반으로 이미지를 처리한다.
i=0;
while(1)
{
Division(inStr[i]);
com=D.dCom;
if(com=='X') break;
switch(com)
{
case 'I':
M=D.m1; N=D.m2;
case 'C':
for(r=1;r<=N;r++)
for(c=1;c<=M;c++)
bitMap[r][c]='O';
break;
case 'L':
c=D.m1;
r=D.m2;
color=D.dColor;
bitMap[r][c]=color;
break;
case 'V':
c=D.m1;
rs=D.m2;
re=D.m3;
color=D.dColor;
if(rs>re) Swap(&rs, &re);
for(r=rs; r<=re;r++)
bitMap[r][c]=color;
break;
case 'H':
cs=D.m1;
ce=D.m2;
r=D.m3;
color=D.dColor;
if(cs>ce) Swap(&cs, &ce);
for(c=cs;c<=ce;c++)
bitMap[r][c]=color;
break;
case 'K':
cs=D.m1;
rs=D.m2;
ce=D.m3;
re=D.m4;
color=D.dColor;
if(rs>re) Swap(&rs, &re);
if(cs>ce) Swap(&cs, &ce);
for(r=rs;r<=re;r++)
for(c=cs;c<=ce;c++)
bitMap[r][c]=color;
break;
case 'F':
c=D.m1;
r=D.m2;
color=D.dColor;
//채우기
Fill(r,c,bitMap[r][c],color);
break;
case 'S':
strcpy(fileName,D.dName);
puts(fileName);
for(r=1;r<=N;r++)
{
for(c=1;c<=M;c++)
putchar(bitMap[r][c]);
putchar('\n');
}
break;
}
i++;
}
return 0;
}
참고풀이 결과]
대한민국의 아름다운 영토, 독도의 겨울
'프로그램 > C언어 1000제' 카테고리의 다른 글
C언어 204제] 암호 깨기 II(Crypt Kicker II) (1) | 2024.12.26 |
---|---|
C언어 203제] 인터프리터(Interpreter) (1) | 2024.12.25 |
C언어 201제] LCD 디스플레이(LCD Display) (0) | 2024.12.20 |
C언어 200제] 여행(The Trip) (0) | 2024.12.20 |
C언어 199제] 지뢰 찾기(Minesweeper) (0) | 2024.12.19 |
댓글