我是柠檬哥,专注编程知识分享。 欢迎关注程序员柠檬橙,编程路上不迷路 私信发送1024打包下载10个G编程资源学习资料 私信发送001获取阿里大神LeetCode刷题笔记 私信发送002获取获取谷歌公司编程代码规范 私信发送003获取10个精美简历模板PDF和Word版 私信发送004获取100道精选C面试题和答案word版 私信发送005获取获取谷歌LeetCode算法笔记 最近有一部关于程序员的电视剧,里边有一段关于期中考试要用程序画一个爱心的桥段。仔细看了一下,发现槽点还不少。 今天就给大家分析下剧中出现的爱心代码,并且来复刻一下最后男主完成的酷炫跳动爱心。 剧中代码赏析 1。首先是路人同学的代码: 虽然剧中说是C语言期中考试,但这位同学的代码名叫draw2。py,一个典型的Python文件,再结合截图中的pen。forward、pen。setpos等方法来看,应该是用turtle海龟作图库来画爱心。那效果通常是这样的: importturtleast t。color(red) t。setheading(50) t。beginfill() t。circle(100,170) t。circle(300,40) t。right(38) t。circle(300,40) t。circle(100,170) t。endfill() t。done() 而不是剧中那个命令行下用1组成的不规则的图形。 2。然后是课代表向路人同学展示的优秀代码: 及所谓的效果: 这确实是C语言代码了,但文件依然是以。py为后缀,并且include前面没有加上,这显然是没法运行的。 里面的内容是可以画出爱心的,用的是这个爱心曲线公式: 然后遍历一个1517的方阵,计算每个坐标是在曲线内还是曲线外,在内部就输出或,外部就是。 用python改写一下是这样的: foryinrange(9,6,1): forxinrange(8,9): print(〔(x10)4〕if(xxyy25)325xxyyyelse,end) print() 效果: 稍微改一下输出,还能做出前面那个全是1的效果: foryinrange(9,6,1): forxinrange(8,9): print(1if(xxyy25)325xxyyyelse,end) print() 但跟剧中所谓的效果相去甚远。 3。最后是主角狂拽酷炫D炸天的跳动爱心: 代码有两个片段: 但这两个片段也不C语言,而是C,且两段并不是同一个程序,用的方法也完全不一样。 第一段代码跟前面一种思路差不多,只不过没有直接用一条曲线,而是上半部用两个圆形,下半部用两条直线,围出一个爱心。 改写成Python代码: size10 forxinrange(size): foryinrange(4size1): dist1((xsize)2(ysize)2)0。5 dist2((xsize)2(y3size)2)0。5 ifdist1size0。5ordist2size0。5: print(V,end) else: print(,end) print() forxinrange(1,2size): foryinrange(x): print(,end) foryinrange(4size12x): print(V,end) print() 运行效果: 第二段代码用的是基于极坐标的爱心曲线,是遍历角度来计算点的位置。公式是: 计算出不同角度对应的点坐标,然后把它们连起来,就是一个爱心。 frommathimportpi,sin,cos importmatplotlib。pyplotasplt nopieces100 dt2pinopieces t0 vx〔〕 vy〔〕 whilet2pi: vx。append(16sin(t)3) vy。append(13cos(t)5cos(2t)2cos(3t)cos(4t)) tdt plt。plot(vx,vy) plt。show() 效果: 代码中循环时用到的2是为了保证曲线长度足够绕一个圈,但其实长一点也无所谓,即使100也不影响显示效果,只是相当于同一条曲线画了很多遍。所以剧中代码里写下35位小数的,还被女主用纸笔一字不落地抄写下来,实在是让程序员无法理解的迷惑行为。 但不管写再多位的,上述两段代码都和最终那个跳动的效果差了五百只羊了个羊。 跳动爱心实现 下面就来挑战一下用Python实现最终的那个跳动爱心的效果。 1。想要绘制动态的效果,必定要借助一些库的帮助,不然代码量肯定会让你感动得想哭。这里我们将使用pgzero库。然后结合最后那个极坐标爱心曲线代码,先绘制出曲线上离散的点。 importpgzrun frommathimportpi,sin,cos nop100 dt23nop t0 x〔〕 y〔〕 whilet23: x。append(16sin(t)3) y。append(13cos(t)5cos(2t)2cos(3t)cos(4t)) tdt defdraw(): screen。clear() foriinrange(len(x)): screen。draw。filledrect(Rect((x〔i〕10400,y〔i〕10300),(4,4)),pink) pgzrun。go() 2。把点的数量增加,同时沿着原点到每个点的径向加一个随机数,并且这个随机数是按照正态分布来的(半个正态分布),大概率分布在曲线上,向曲线内部递减。这样,就得到这样一个随机分布的爱心效果。 。。。 nop20000 。。。 whilet2pi: l10abs(random。gauss(10,2)10) x。append(l16sin(t)3) y。append(l(13cos(t)5cos(2t)2cos(3t)cos(4t))) tdt 。。。 3。下面就是让点动起来,这步是关键,也有一点点复杂。为了方便对于每个点进行控制,这里将每个点自定义成了一个Particle类的实例。从原理上来说,就是给每个点加一个缩放系数,这个系数是根据时间变化的正弦函数,看起来就会像呼吸的节律一样。 classParticle(): definit(self,pos,size,f): self。pospos self。pos0pos self。sizesize self。ff defdraw(self): screen。draw。filledrect(Rect((10self。fself。pos〔0〕400,10self。fself。pos〔1〕300),self。size),hotpink) defupdate(self,t): df1(21。5)sin(t3)8 self。posself。pos0〔0〕df,self。pos0〔1〕df 。。。 t0 defdraw(): screen。clear() forpinparticles: p。draw() defupdate(dt): globalt tdt forpinparticles: p。update(t) 4。剧中爱心跳动时,靠中间的点波动的幅度更大,有一种扩张的效果。所以再根据每个点距离原点的远近,再加上一个系数,离得越近,系数越大。 classParticle(): 。。。 defupdate(self,t): df1(21。5self。f)sin(t3)8 self。posself。pos0〔0〕df,self。pos0〔1〕df 5。最后再用同样的方法画一个更大一点的爱心,这个爱心不需要跳动,只要每一帧随机绘制就可以了。 defdraw(): 。。。 t0 whilet2pi: frandom。gauss(1。1,0。1) x16sin(t)3 y13cos(t)5cos(2t)2cos(3t)cos(4t) size(random。uniform(0。5,2。5),random。uniform(0。5,2。5)) screen。draw。filledrect(Rect((10fx400,10fy300),size),hotpink) tdt3 合在一起,搞定! 总结一下,就是在原本的基础爱心曲线上加上一个正态分布的随机量、一个随时间变化的正弦函数和一个跟距离成反比的系数,外面再套一层更大的随机爱心,就得到类似剧中的跳动爱心效果。 但话说回来,真有人会在考场上这么干吗? 除非真的是超级大学霸,不然就是食堂伙食太好,吃太饱撑的