[ACM]图形编辑器

18 篇文章 0 订阅
13 篇文章 0 订阅

原题见:http://acm.uva.es/p/v102/10267.html

背景

图形编辑器(graphical editor)允许用户改变位图图像,比如大家经常用到的Photoshop。它所采用的改变方法和文本编辑器允许修改文档的方法一样。位图图像由MxN的像素矩阵来表示,并且每个像素点都有给定的颜色。

我们的任务就是来要编写一个程序来模拟一个简单的交互式图形编辑器。

输入

输入由一组编辑命令序列组成,每条序列占一行。每个命令都是由一个大写字母表示的,且放在每行序列首字符的位置上。如果命令需要带参数,那么给出的参数将和命令放在同一行,并用空格相互隔开。 像素点的坐标用两个整数表示,列坐标的范围是从1到M,而行坐标的范围则是从1到N(1<M,N<=250)。坐标原点位于矩阵的左上角。像素点的颜色由大写字母指定。

下面描述了图形编辑器可以接收的命令内容:

I M N表示产生一个新的MxN大小的图像,并且图像中所有像素点的初始颜色都为白色(0)。
C表示通过把所有像素点设置为白色的方法来清除表格。且矩阵的大小保持不变。
L X Y C表示把坐标为(X,Y)的像素点的颜色涂成颜色(C)。
V X Y1 Y2 C表示画一条颜色为(C)的垂直线段,线段的列坐标为X,行坐标在Y1到Y2之间,并且包括Y1和Y2两点。
H X1 X2 Y C表示画一条颜色为(C)的水平线段,线段的行坐标为Y,列坐标在X1到X2之间,并且包括X1和X2两点。
K X1 Y1 X2 Y2 C表示画一个填充颜色为(C)的矩形,坐标(X1,Y1)和(X2,Y2)表示矩形相对的两个角。
F X Y C表示用颜色(C)填充区域R。区域R的定义如下:像素点(X,Y)属于区域R。和像素点(X,Y)颜色一样,并且与区域R内的任何像素点共享一个公共边的其他任何像素点也都属于区域R。
S Name表示用MSDOS 8.3的格式写文件名,并且文件名后边跟着当前图像的内容。
X表示终止此次对话操作。

输出

在执行每一个S NAME命令时,打印出用NAME(不超过70个字符)命名的文件名(占一行),以及当前图像的内容。图像的每一行用每个像素点的颜色内容来表示。参见输出样例。

输出要忽略掉不用上述字母(即I、C、L、V、H、K、F、S和X)定义的任何命令行,并且继续执行下面的命令。遇到其他错误情况时,程序的运行将无法预测。

来源

http://acm.uva.es/p/v102/10267.html

测试输入帮助,input (新窗口)期待的输出帮助,expectedoutput (新窗口)时间限制帮助,timelimit (新窗口)内存限制帮助,memlimit (新窗口)额外进程帮助,nproc (新窗口)
测试用例 1 以文本方式显示
  1. I 5 6↵
  2. L 2 3 A↵
  3. S one.bmp↵
  4. G 2 3 J↵
  5. F 3 3 J↵
  6. V 2 3 4 W↵
  7. H 3 4 2 Z↵
  8. S two.bmp↵
  9. X↵
以文本方式显示
  1. one.bmp↵
  2. 00000↵
  3. 00000↵
  4. 0A000↵
  5. 00000↵
  6. 00000↵
  7. 00000↵
  8. two.bmp↵
  9. JJJJJ↵
  10. JJZZJ↵
  11. JWJJJ↵
  12. JWJJJ↵
  13. JJJJJ↵
  14. JJJJJ↵
1秒 1024KB 0
测试用例 2 以文本方式显示
  1. I 11 9↵
  2. F 1 1 `↵
  3. H 1 11 1 O↵
  4. H 1 11 9 O↵
  5. V 1 2 8 O↵
  6. V 11 2 8 O↵
  7. L 4 3 O↵
  8. L 3 4 O↵
  9. L 8 3 O↵
  10. L 9 4 O↵
  11. K 3 6 9 9 O↵
  12. H 4 8 7 `↵
  13. H 4 8 8 `↵
  14. S JIONG.BMP↵
  15. X↵
以文本方式显示
  1. JIONG.BMP↵
  2. OOOOOOOOOOO↵
  3. O`````````O↵
  4. O``O```O``O↵
  5. O`O`````O`O↵
  6. O`````````O↵
  7. O`OOOOOOO`O↵
  8. O`O`````O`O↵
  9. O`O`````O`O↵
  10. OOOOOOOOOOO↵
1秒 1024KB 0
      这个题目比较直接,唯一的难点在于F操作:表示用颜色(C)填充区域R,可以用DFS实现,通过递归,因为是字符操作,不是特别 复杂,不会操作内存限制!还可以采用BFS,这要借助队列,可以定义一个N * N行 2 列的一个二维数组,这样实现起来比较复杂, 但是节省了时间和空间,我采用的是递归的DFS实现,见代码:

#include <stdio.h>
#include <string.h>
#define M 250
char graph[M][M], scolor;
int rows, cols;
void FillColor(int x, int y, char color)
{
	if (graph[x][y] == scolor && x >= 1 && y >= 1 && x <= rows && y <= cols)
	{
		graph[x][y] = color;
		FillColor(x + 1, y, color);
		FillColor(x - 1, y, color);
		FillColor(x , y + 1, color);
		FillColor(x , y - 1, color);
	}
}
int main()
{
	//freopen("in.txt", "r", stdin);
	char cmd, color,name[100];
	int x,y,x1,x2,y1,y2,i,j,k;
	while (scanf("%c", &cmd) != EOF)
	{
		if (cmd == 'X') return 0;
		switch (cmd)
		{
		case 'I': scanf("%d %d\n", &cols, &rows);
			memset(graph, '0', M * M);
			break;
		case 'C': getchar();
			memset(graph, '0', M * M); 
			break;
		case 'L': scanf("%d %d %c\n", &x, &y, &color);
			graph[y][x] = color; 
			break;
		case 'V': scanf("%d %d %d %c\n", &x, &y1, &y2, &color);
			if(y1>y2)
			{
				k=y1;y1=y2;y2=k;
			}
			for (i = y1; i <= y2; i++)
				graph[i][x] = color;
			break;
		case 'H': scanf("%d %d %d %c\n", &x1, &x2, &y, &color);
			if(x1>x2)
			{
				k=x1;x1=x2;x2=k;
			}
			for (i = x1; i <= x2; i++)
				graph[y][i] = color;
			break;
		case 'K': scanf("%d %d %d %d %c\n", &x1, &y1, &x2, &y2, &color);
			if(x1>x2)
			{
				k=x1;x1=x2;x2=k;
			}
			if(y1>y2)
			{
				k=y1;y1=y2;y2=k;
			}
			for (i = x1; i <= x2; i++)
				for (j = y1; j <= y2; j++)
					graph[j][i] = color;
			break;
		case 'F': scanf("%d %d %c\n", &x, &y, &color);
			scolor = graph[y][x];
			if (color == scolor) break; //这里一定要加以判断,只有颜色不同的时候才要启动填充哦,否则会陷入死循环!JOL会报内存引用出错!
			FillColor(y, x, color);
			break;
		case 'S': scanf(" %[^\n]\n",name);
			printf("%s\n", name);
			for (i = 1; i <= rows; i++)
			{
				for (j = 1; j <= cols; j++)
					printf("%c", graph[i][j]);
				printf("\n");
			}
			break;
		default: scanf("%s\n",name);
			break;
		};
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值