门格海绵解决思路:
1. 迭代如何实现
2. 立方体该怎么画
3. 实现门格海绵代码
4. 画图板+门格海绵代码
1. 迭代如何实现
为了实现从1图—>2图—>3图效果,我们就要想到用迭代去实现.
因为像3图这样的图形,是由若干个2图这样的基本图形组成的
那么,怎样实现镂空的效果呢?
观察2图
2图的正方体可以分成3层结构:
下层有8个小正方体,中层有4个,上层有8个.
所以我们现在思考的就是怎样画出基本图形的这三层
但是在画之前,我们先思考一下:哪一层先画呢:?
如果是按上–>中–>下的顺序,我们会得到:
很明显,这和我们所需要的图形是不一致的
所以答案是:下–>中–>上
那么,问题又来了,每一层的的小正方体是按什么顺序画呢?
通过上一个问题的测试,我们可以知道,每一层的正方体,距离我们近的后画,距离我们远的先画,才会达到立方体正确叠加的效果.
2. 立方体该怎么画
好了.确定完上面这些,我们再来确定最基本的问题,正方体该怎么画?
(x,y)正方体正面左上角的点
dx,dy:因为我们在视觉上除了正面是正方形,其余面都是平行四边形,所以增加一个偏移值
d:正方体的边长
有了这些值,我们就可以确定各个顶点的坐标
颜色的话,自由发挥,只要颜色深度:上面>右侧面>正面,且
//上面
int[] xs1={x,x+d,x+d+dx,x+dx};
int[] ys1={y,y,y-dy,y-dy};
g.setColor(new Color(0,50,50));
g.fillPolygon(xs1, ys1, 4);//fillPolygon就是画填充多边形,传进的参数就是x坐标的数组,y坐标的数组,顶点的数量
//右侧面
int[] xs2={x+d,x+d+dx,x+d+dx,x+d};
int[] ys2={y,y-dy,y-dy+d,y+d};
g.setColor(new Color(0,100,100));
g.fillPolygon(xs2, ys2, 4);
//正面
g.setColor(new Color(0,160,160));
g.fillRect(x, y, d, d);
3. 实现门格海绵代码
因为画正方体的过程是先画最里层,最小的,才有叠加的效果,所以,只要迭代没进行到底,还要继续迭代,再去画正方体
public void drawSponge(Graphics g,int n,int x,int y,int dx,int dy,int d){
//n为迭代的层数
//从里往外画,从上往下画
n--;
if(n>0){
//最下层
drawSponge(g,n,x+2*dx/3,y-2*dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+d/3,y-2*dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+2*d/3,y-2*dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3,y-dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3+2*d/3,y-dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x,y+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+d/3,y+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*d/3,y+2*d/3,dx/3,dy/3,d/3);
//中间层
drawSponge(g,n,x+2*dx/3,y-2*dy/3+d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+2*d/3,y-2*dy/3+d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x,y+d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*d/3,y+d/3,dx/3,dy/3,d/3);
//最上层
drawSponge(g,n,x+2*dx/3,y-2*dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+d/3,y-2*dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+2*d/3,y-2*dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3,y-dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3+2*d/3,y-dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x,y,dx/3,dy/3,d/3);
drawSponge(g,n,x+d/3,y,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*d/3,y,dx/3,dy/3,d/3);
}else{
int[] xs1={x,x+d,x+d+dx,x+dx};
int[] ys1={y,y,y-dy,y-dy};
g.setColor(new Color(0,50,50));
g.fillPolygon(xs1, ys1, 4);
int[] xs2={x+d,x+d+dx,x+d+dx,x+d};
int[] ys2={y,y-dy,y-dy+d,y+d};
g.setColor(new Color(0,100,100));
g.fillPolygon(xs2, ys2, 4);
g.setColor(new Color(0,160,160));
g.fillRect(x, y, d, d);
}
}
4. 画图板+门格海绵代码
我们把门格海绵加到画图板上
并且添加按钮,实现,点击按钮后,根据之后按下的点的坐标画图的效果
画图板类:
import javax.swing.JFrame; //窗体
import javax.swing.JButton; //按钮
import java.awt.FlowLayout; //流式布局器
import java.awt.Graphics; //画笔
public class DrawPad {
public static void main(String args[]){
DrawPad dp = new DrawPad();
dp.showUI();
}
public void showUI(){
JFrame jf = new JFrame();
DrawPadListener dl = new DrawPadListener();
JButton btn = new JButton("门格海绵");
btn.setName("门格海绵");
btn.addActionListener(dl);
jf.add(btn);
}
FlowLayout fl = new FlowLayout();
jf.setTitle("可视化"); //名称
jf.setSize(800,600); //尺寸
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //关闭进程
jf.setLayout(fl); //设置流式布局
jf.setResizable(false); //不可以改变窗体大小
jf.setLocationRelativeTo(null);//居中显示
jf.addMouseListener(dl);
jf.setVisible(true); //设置窗体可视
Graphics g = jf.getGraphics();
dl.g = g;
}
}
画图板监听器类:
import java.awt.Color; //颜色
import java.awt.Graphics; //画笔
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;//动作监听器
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; //鼠标监听器
public class DrawPadListener implements MouseListener, ActionListener{
String btnstr;//记录按钮的字符串
Graphics g;
int x1,x2,y1,y2;
int n = 1;//迭代层数,自己去改
public void actionPerformed(ActionEvent e){
btnstr = e.getActionCommand();
System.out.println("actionPerformed方法被调用,btnstr为:"+btnstr);
}
public void mouseClicked(MouseEvent e){
System.out.println("点击");
}
public void mousePressed(MouseEvent e){
System.out.println("按下");
x1=e.getX();
y1=e.getY();
}
public void mouseReleased(MouseEvent e){
System.out.println("释放");
x2=e.getX();
y2=e.getY();//释放点的坐标
if(btnstr.equals("门格海绵"))
drawSponge(g,n,x1,y1,99,99,198);//数值可以自己改
//友情提示:dx,dy,d尽量选择3的倍数,不要海绵上可能会出现一条明显的直线
}
public void mouseEntered(MouseEvent e){
System.out.println("进入");
}
public void mouseExited(MouseEvent e){
System.out.println("退出");
}
public void drawSponge(Graphics g,int n,int x,int y,int dx,int dy,int d){
//从里往外画,从上往下画
n--;
if(n>0){
//最下层
drawSponge(g,n,x+2*dx/3,y-2*dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+d/3,y-2*dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+2*d/3,y-2*dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3,y-dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3+2*d/3,y-dy/3+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x,y+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+d/3,y+2*d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*d/3,y+2*d/3,dx/3,dy/3,d/3);
//中间层
drawSponge(g,n,x+2*dx/3,y-2*dy/3+d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+2*d/3,y-2*dy/3+d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x,y+d/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*d/3,y+d/3,dx/3,dy/3,d/3);
//最上层
drawSponge(g,n,x+2*dx/3,y-2*dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+d/3,y-2*dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*dx/3+2*d/3,y-2*dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3,y-dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x+dx/3+2*d/3,y-dy/3,dx/3,dy/3,d/3);
drawSponge(g,n,x,y,dx/3,dy/3,d/3);
drawSponge(g,n,x+d/3,y,dx/3,dy/3,d/3);
drawSponge(g,n,x+2*d/3,y,dx/3,dy/3,d/3);
}else{
int[] xs1={x,x+d,x+d+dx,x+dx};
int[] ys1={y,y,y-dy,y-dy};
g.setColor(new Color(0,50,50));
g.fillPolygon(xs1, ys1, 4);
int[] xs2={x+d,x+d+dx,x+d+dx,x+d};
int[] ys2={y,y-dy,y-dy+d,y+d};
g.setColor(new Color(0,100,100));
g.fillPolygon(xs2, ys2, 4);
g.setColor(new Color(0,160,160));
g.fillRect(x, y, d, d);
}
}
}