递归函数画雪花(宇宙的奥秘:递归、分形、循环)

本文目录
宇宙的奥秘:递归、分形、循环
递——是传递,归——是回归。那么从传递开始回归到传递的开始,就是从一个地方出发,回到了出发的地方,就完成了一次循环,而不断重复这个循环,就是 递归 。
有两个特质:循环嵌套,自身构建。
瑞克和莫蒂》第二季第六集——递归的电池微世界 。
分形:通常被定义为一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状,即具有自相似的性质。比如,雪花、晶体、弯弯曲曲的海岸线
重复性对称和递归性对称, 其实这两者都是分形自构建所产生的表现。那么在微观,我们可以看到对称性的破缺,这其实是递归过程——循环层级加深,所带来的效应。
***隐藏网址***
递归写Koch雪花的算法
现在绘制3条Koch曲线就构成了Koch雪花。
kochCurve(x0, y0, angle, length, n);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle -= pi*2/3;
kochCurve(x0, y0, angle, length, n);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle -= pi*2/3;
kochCurve(x0, y0, angle, length, n);
下一次的迭代同样要用到这样的方法,所以我们可以把这些代码放倒kochCurve函数中。于是kochCurve成了一个递归函数。
为了控制递归的深度,我们需要给kochCurve添加一个参数n。
void kochCurve(double x0, double y0, double angle, double length, int n)
{
if(n == 0) {
double x1 = x0 + length*cos(angle);
double y1 = y0 + length*sin(angle);
glBegin(GL_LINES);
glVertex2d(x0, y0);
glVertex2d(x1, y1);
glEnd();
}
else {
length /= 3;
n --;
kochCurve(x0, y0, angle, length, n);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle += pi/3;
kochCurve(x0, y0, angle, length, n);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle -= pi*2/3;
kochCurve(x0, y0, angle, length, n);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle += pi/3;
kochCurve(x0, y0, angle, length, n);
}
}
n是函数递归的层数,也是Koch曲线迭代的次数。
kochCurve(x0, y0, angle, length, 0)画出的是初始的图形
kochCurve(x0, y0, angle, length, 1)画出第一次迭代
下面是n = 2, 3, 4, 5的结果。
这里用线段的起点(x0, y0),方向(和正向x轴之间的角度)及长度来描述一条线段。
绘制一条从(-1.0, 0.0)到(1.0, 0.0)的Koch曲线用下面的方法:
double length = 2.0;
double angle = 0.0;
double x0 = -1.0;
double y0 = 0.0;
kochCurve(x0, y0, angle, length);
一条Koch曲线是由4条比例缩写为整体1/3的Koch曲线组成。
length = 2.0/3;
kochCurve(x0, y0, angle, length);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle += pi/3;
kochCurve(x0, y0, angle, length);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle -= pi*2/3;
kochCurve(x0, y0, angle, length);
x0 += length*cos(angle);
y0 += length*sin(angle);
angle += pi/3;
kochCurve(x0, y0, angle, length);
这样就画出了第一次迭代的结果。
理论上说,Koch曲线是由无数无限短的线段组成。绘图的时候当然不可能画出无限短的线段。所以我们根据要求,用若干线段组成。
首先,绘制构造Koch曲线的初始图形,也就是一条直线。
void kochCurve(double x0, double y0, double angle, double length)
{
double x1 = x0 + length*cos(angle);
double y1 = y0 + length*sin(angle);
glBegin(GL_LINES);
glVertex2d(x0, y0);
glVertex2d(x1, y1);
glEnd();
}
如何使用less实现随机下雪动画详解
冬天来了,设计师说摇摇乐的场景需要随机下落的雪花动画,第一时间就想到的方法是canvas比较好,项目非常紧急,然而小程序对canvas支持不够友好,容易在项目中出现无法预估的兼容性问题 ,马上又否定了这种想法,想了想用javascript来写随机动画成本又高。既不用canvas也不用javascript来实现,最终决定使用css预处理器less来实现随机雪花,less怎么可能实现随机雪花?对于喜欢写css的人来说,这非常有趣。【推荐教程:CSS教程】
上图的雪花效果还蛮炫酷吧,怎么实现呢?less因为有以下的2个特点,可以尝试使用它来实现我们的场景
1.递归调用
实际上less并没有自带类似javascript的for循环的功能,但less可以用过引导when来实现条件判断,简单的方法也可以让聪明的程序员简单实现递归调用
.snow(@n) when (@n 》 0) {
fn()//生成雪花函数fn(
.snow((@n - 1));//再次执行函数fn()
}
.snow(60);//执行次数2.避免编译JavaScript 表达式
雪花需要生成的随机数,我们需要运用javascript表达式嵌入到less代码,同时也要避免javascript表达式被less错误的编译,我们需要了解两个点。
一些 LESS不认识的专有语法,可以在字符串前加上一个 ~,
JavaScript 表达式在less 文件中使用,可以通过反引号的方式使用
于是有了如下随机位移、随机时间、随机大小的代码
于是有了如下的Less代码,具体怎么实现请留意详细的代码注释
以下less代码使用构建后可生产一份随机css固定雪花文件,决定了每一个雪花有不同的大小、水平位移、垂直位移、出场位置、出场时间,不同的雪花大小,不同的下落速度,用肉眼看到的雪花就像是随机的,可以在项目上线前尝试多构建几次,得到一份均匀分布在窗口的随机雪花。
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
}
//浏览器窗口宽度
@windowWidth: 750;
//雪花
.snow {
&_wrap{
position: relative;
width: ~"@{windowWidth}px";
height: 100%;
overflow: hidden;
background: rgba(14,99,69,1);
margin: 0 auto;
}
//雪花初始化大小
position: absolute;
width:20px;
height: 20px;
&:after{
content: ’’;
position: absolute;
left:0;
top:0;
width:20px;
height: 20px;
background-color:#fff;
opacity:1;
border-radius: 100%;
filter:blur(5px);//此处使用css3滤镜来画雪花
}
}
//随机雪花函数
.snow(@n) when (@n 》 0) {
.snow_@{n}{
//水平方向上的位移
left: ~"`Math.round(Math.random() * @{windowWidth})`px";
//动画运行时间8~12秒,保证雪花有不同的移动速度
animation: ~"snowani_@{n} `(-Math.random() * 4 + 8).toFixed(2)`s linear infinite";
//动画提前出场时间,也就是垂直方向上位移
animation-delay: ~"`(-Math.random() * 8 + 0.2).toFixed(2)`s";
&:after{
//雪花大小随机,0.5~1.2
transform: ~"scale(`(Math.random() * 0.7 + 0.5).toFixed(2)`)";
}
}
@keyframes ~"snowani_@{n}" {
0%{
transform: translateY(0);
}
100%{
//垂直方向上高度,保证雪花有不同的移动速度
transform: ~"translateY(`Math.round(Math.random() * 200 + 1600)`px)";
}
}
.snow((@n - 1));
}
.snow(60);//生成雪花的数量把上面的雪花的代码构建后如下:
还有HTML,一行代码的事情
在器中安装好emmet或webstorm开启emmet后,输入下面代码按下ctrl+e快捷键即可生成60个不同命名的雪花标签

更多文章:
全球新冠肺炎疫情背景下航运发展(盐田港复苏日志:半年历劫从“低谷”到“爆仓” 疫情之后巨轮如何越洋航行)
2026年9月7日 17:10
matlab求解带字母参数方程组(我想matlab求一个关于x,y的方程组 ab c d f e h m n 都是参数)
2026年9月7日 16:30
oracle中的循环语句(下面哪个不是oracle程序设计中的循环语句 a for)
2026年9月7日 15:30
电脑里2个系统怎么删除一个(电脑开机显示有两个系统,如何删除一个)
2026年9月7日 12:20
scrollthrough意思(“scroll”是什么意思)
2026年9月7日 08:00
怎么激活keygen(注册机如何激活cad2008一个简单激活cad2008的方法)
2026年9月7日 06:30



