挑战编程 程序设计竞赛训练手册-1.6.5 图形化编辑器(Graphical Editor)

挑战编程 程序设计竞赛训练手册-1.6.5 图形化编辑器(Graphical Editor)

public class problem_Graphical_Editor {

	/**
	 * @param args
	 */
	/*个人认为此程序难点在于 
	 * 1、操作字符 F ,即填充某一个区域,需要算法支持,其中越界处理和全面覆盖处理需注意。
	 * 2、代码块之间的变量不能互传,需要设计一个全局变量来存储更新
	 * 		(第一次我把方法都写在case中,然后运算的结果就是穿不出去,非常蛋疼!
	 * 			更改代码后,只利用case来判断操作符,判断完成立刻并转入方法进行操作,
	 * 			并适当加入全局变量,以保证数值的成功传递)*/
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String[] str = { "I 5 6", //设定字符串
						"C", 
						"L 2 3 A", 
						//"K 4 5 4 5 I",//测试K操作
						"S one.bmp", 
						//"C",    //测试清空操作
						"G 2 3 J",// 不在指令范围,应无操作
						/*"H 3 5 2 Z",
						"L 1 2 Z",//测试F操作*/
						"F 3 3 J", 
						//"F 4 4 K",//再次测试F操作
						"V 2 3 4 W", 
						"H 3 4 2 Z", 
						"S two.bmp", 
						"X" };
		String get="";//定义截取字符数组的字符串变量为空,等待截取输入内容
		int Row = 0;//定义图片列数
		int Line = 0;//定义图片行数
		char[][] pic = null;//新建二维字符空图片
		for (int i=0;i<str.length;i++){//逐一截取字符串变量
			get = str[i];	
		char R = get.substring(0).charAt(0);// 截取首字母,判断操作
		switch (R) { //判断操作符,顺便准备下将传入方法的变量
		case 'I':
			System.out.println("新建一个Line×Row的图像——所有像素为白色(-null符号-)");
			/*截取列和行的大小*/ 
			 Row = Integer.parseInt(get.substring(get.indexOf(' ') + 1,
					get.lastIndexOf(' ')));
			 Line = Integer.parseInt(get.substring(get.lastIndexOf(' ') + 1,
					get.length()));
			 /*新建一个空图像*/
			 pic = new char[Line][Row];
			break;
		case 'C':
			System.out.println("清除所有图像——所有像素涂成白色(O),大小不变");
			/*清除图像=新建空图像,长宽为更新的Line和Row*/
			pic = new char[Line][Row];
			break;
		case 'L':
			System.out.println("像素(X,Y)涂成颜色(C)");
			/*截取涂色的X,Y坐标和颜色C*/
			int Ly = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));
			/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
			 * 第一个空格位置为初始位置 , 结束位置为 从第一个空格的后面一个位置开始算起的第一个空格
			 * 然后截断字符↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓去掉第一个空格之前的所有,继续上述操作,直到截完整个字符串。*/
			get = get.substring(get.indexOf(' ')+1,get.length());//截断字符串,为2 3 A
			/*这样一次次截断有点二,可以写个方法调用下~~~~~~~~~~~~~~懒得更新了*/
			int Lx = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));
			get = get.substring(get.indexOf(' ')+1,get.length());//再次截断字符串,为3 A
			char LC = get.substring(get.indexOf(' ')+1,get.length()).toCharArray()[0];
			/*最后一个是字符,表示颜色,截取后可以用toCharArray()转换为字符数组。
			 * 因为只有一个字符,所以果断toCharArray()[0]
			 * 由于操作符后面跟进的数字和字符的数量(不是数字的位数)是限定的,因此可以用上述方法依次截取和判断
			 * 下面的方法都是这个思路,不再重复说明*/
			System.out.println(Ly+" "+Lx+" "+LC);
			/*进行涂色操作,并返回图像*/
			pic = paintLG(pic,Ly,Lx,LC);
			break;
		case 'V':
			System.out.println("画一条竖线段——颜色为(C),列号为X,从第Y1行到第Y2行(包括Y1和Y2行)");
			/*截取涂色竖直线段的X,Y坐标和颜色C,截取算法参考case 'L'*/
			int Vy = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//X行在y轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			//继续二
			int Vx1 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			int Vx2 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			char VC = get.substring(get.indexOf(' ')+1,get.length()).toCharArray()[0];
			System.out.println(Vy+" "+Vx1+" "+Vx2+" "+VC);
			/*进行竖直线段的涂色操作,并返回图像*/
			pic = paintVG(pic,Vy,Vx1,Vx2,VC);
			break;
		case 'H':
			System.out.println("画一条水平线段——颜色为(C),行号为Y,从第X1行到第X2行(包括X1和X2行)");
			/*截取涂色水平线段的X,Y坐标和颜色C,截取算法参考case 'L'*/
			int Hy1 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//X行在y轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			//还是二
			int Hy2 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			int Hx = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			char HC = get.substring(get.indexOf(' ')+1,get.length()).toCharArray()[0];
			System.out.println(Hy1+" "+Hy2+" "+Hx+" "+HC);
			/*进行竖直线段的涂色操作,并返回图像*/
			pic = paintHG(pic,Hy1,Hy2,Hx,HC);
			break;
		case 'K':
			System.out.println("画一个实心矩形——颜色为(C),左上角为(X1,Y1),右下角为(X2,Y2)");
			/*截取涂色实心矩形的X,Y坐标和颜色C,截取算法参考case 'L'*/
			int Ky1 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//X行在y轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			//………………弱爆了,有时间的话把它改写成方法……重复的那么多显得没水准
			int Ky2 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			int Kx1 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			int Kx2 = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));//Y列在x轴上
			get = get.substring(get.indexOf(' ')+1,get.length());
			char KC = get.substring(get.indexOf(' ')+1,get.length()).toCharArray()[0];
			System.out.println(Ky1+" "+Ky2+" "+Kx1+" "+Kx2+" "+KC);
			/*进行实心矩形的涂色操作,并返回图像*/
			pic = paintKG(pic,Ky1,Ky2,Kx1,Kx2,KC);
			break;
		case 'F':
			System.out.println("把区域R填充为颜色(C)——R定义如下:若像素(X,Y)属于R,则所有与(X,Y)有公共边且颜色相同的像素也属于R");
			/*截取涂色的X,Y坐标和颜色C*/
			int Fy = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));
			get = get.substring(get.indexOf(' ')+1,get.length());
			int Fx = Integer.parseInt(get.substring(get.indexOf(' ')+1,get.indexOf(' ',get.indexOf(' ')+1)));
			get = get.substring(get.indexOf(' ')+1,get.length());
			char FC = get.substring(get.indexOf(' ')+1,get.length()).toCharArray()[0];
			System.out.println(Fy+" "+Fx+" "+FC);
			/*进行区域X,Y的填充,并返回图像*/
			char color = getColor(pic,Fy,Fx);
			pic = paintFG(pic,Fy,Fx,FC,Row,Line,color);
			break;
		case 'S':
			String picName = get.substring(2, get.length());// 截取文件名
			System.out.println("原样输出文件名以及整幅图像的像素矩阵");
			System.out.println(picName);// 直接输出文件名
			/* 输出图像 */
			showG(pic);
			break;
		case 'X':
			System.out.println("退出程序");
			break;
		default:
			break;
			}
		}
	}
	
	/*获取指定位置字符(即颜色,下文的字符即表示颜色)
	 * 传入 二维char图片,指定位置行号,指定位置列号
	 * return 颜色字符*/
	private static char getColor(char[][] pic, int fy, int fx) {
		// TODO Auto-generated method stub
		char color= pic[fy-1][fx-1];
		return color;
	}
	
	/*下列方法的 命名规则 paint+操作字符代码+G
	 */
	 
	/*此方法传入 二维char图片,指定位置行号,指定位置列号,替代字符,列数,行数,等待变换的字符
	 * 返回更新后的二维字符组成的图片*/
	private static char[][] paintFG(char[][] pic, int fy, int fx, char fC,int Row,int Line,char color) {
		// TODO Auto-generated method stub
		//定义--若像素(X,Y)属于R,则所有与(X,Y)有公共边且颜色相同的像素也属于R
		/*采用递归算法:
		 * 大致思路:
		 *从判断指定位置开始,
		 *由getcolor记录待更改的颜色,
		 *在改变当前位置字符后,
		 *用getcolor记录到的字符判断上下左右相邻的四个字符
		 *如果某一位置的字符和getcolor获取的一样,
		 *则递归,以此类推
		 *————————————分割线————————
		 *较繁琐的是越界问题,
		 *如果某一位置的周围字符超出了图片范围,
		 *不能对其进行修改,否则报越界错误。
		 *我的程序是在图片的四个顶角处完全停止递归
		 *因为能完全覆盖图片
		 *详情见↓下方代码↓ */
		if(fy<=1||fy>=Line){//如果贴上边和下边(其实直接等于就够了,程序是达不到越界范围的。
							//只是习惯了加上大于小于的范围判断,不知是否会影响性能??)
			if(fx<=1||fx>=Row){//如果贴左边和右边,即到顶,直接判断此框,停止递归
				if(pic[fy-1][fx-1]==color){ //更新(字符)颜色
					pic[fy-1][fx-1]=fC;
				}
			}else{//否则左右移动(只是贴于上下边,则进行左右位置的递归)
				if(pic[fy-1][fx-1]==color){//更新(字符)颜色
					pic[fy-1][fx-1]=fC;
					paintFG(pic,fy,fx-1,fC,Row,Line,color);//向左递归
					paintFG(pic,fy,fx+1,fC,Row,Line,color);//向右递归			
				}	
			}
		}else{//如果没有在上边和下边
			if(fx<=1||fx>=Row){//如果贴左边和右边,则上下移动
				if(pic[fy-1][fx-1]==color){//更新(字符)颜色
					pic[fy-1][fx-1]=fC;
					paintFG(pic,fy-1,fx,fC,Row,Line,color);//向上递归
					paintFG(pic,fy+1,fx,fC,Row,Line,color);//向下递归			
				}	
			}else{//否则上下左右移动
				if(pic[fy-1][fx-1]==color){//更新(字符)颜色
					pic[fy-1][fx-1]=fC;
					paintFG(pic,fy,fx-1,fC,Row,Line,color);//向上下左右四格递归
					paintFG(pic,fy,fx+1,fC,Row,Line,color);
					paintFG(pic,fy-1,fx,fC,Row,Line,color);
					paintFG(pic,fy+1,fx,fC,Row,Line,color);
				}	
			}
		}
		return pic;
	}
	
	/*以下算法非常简单,不再过多注释*/
	private static char[][] paintKG(char[][] pic, int ky1, int ky2, int kx1,
			int kx2, char kC) {
		// TODO Auto-generated method stub
		for (int i=ky1-1;i<=ky2-1;i++){
			for(int j=kx1-1;j<=ky2-1;j++){
				pic[i][j] = kC;
			}
		}
		return pic;
	}

	private static char[][] paintHG(char[][] pic, int hy1, int hy2, int hx,
			char hC) {
		// TODO Auto-generated method stub
		for (int i=hy1-1;i<=hy2-1;i++){
			pic[hx-1][i] = hC;
		}
		return pic;
	}

	private static char[][] paintVG(char[][] pic, int vy, int vx1, int vx2,
			char vC) {
		// TODO Auto-generated method stub
			for (int i=vx1-1;i<=vx2-1;i++){
				pic[i][vy-1] = vC;
			}
		return pic;
	}

	private static char[][] paintLG(char[][] pic,int Line,int Row,char c) {
		// TODO Auto-generated method stub
			pic[Line-1][Row-1] = c;
		return pic;
	}

	private static void showG(char[][] pic) {
		// TODO Auto-generated method stub
		for( int i=0;i<pic.length;i++){
			for (int j=0;j<pic[i].length;j++){
				System.out.print(pic[i][j]);
			}
			System.out.println("");
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值