电视剧里的代码真能运行吗?

简介: 用Python送你一颗跳动的爱心

大家好,欢迎来到 Crossin的编程教室 !

前几天,后台老有小伙伴留言“爱心代码”。这不是Crossin很早之前发过的内容嘛,怎么最近突然又被人翻出来了?后来才知道,原来是一部有关程序员的青春偶像剧《点燃我,温暖你》在热播,而剧中有一段关于期中考试要用程序画一个爱心的桥段。

于是出于好奇,Crossin就去看了这一集(第5集,不用谢)。这一看不要紧,差点把刚吃的鸡腿给喷出来--槽点实在太多了!

忍不住做了个欢乐吐槽向的代码解读视频,在某平台上被顶到了20个w的浏览,也算蹭了一波人家电视剧的热度吧……

下面是图文版,给大家分析下剧中出现的“爱心”代码,并且来复刻一下最后男主完成的酷炫跳动爱心。

剧中代码赏析

  1. 首先是路人同学的代码:

image.png

虽然剧中说是“C语言期中考试”,但这位同学的代码名叫 draw2.py,一个典型的 Python 文件,再结合截图中的 pen.forward、pen.setpos 等方法来看,应该是用 turtle 海龟作图库来画爱心。那效果通常是这样的:

import turtle as t

t.color('red')

t.setheading(50)

t.begin_fill()

t.circle(-100, 170)

t.circle(-300, 40)

t.right(38)

t.circle(-300, 40)

t.circle(-100, 170)

t.end_fill()

t.done()

heart1.gif

而不是剧中那个命令行下用1组成的不规则的图形。

  1. 然后是课代表向路人同学展示的优秀代码:

image.png

及所谓的效果:

image.png

这确实是C语言代码了,但文件依然是以 .py 为后缀,并且 include 前面没有加上 #,这显然是没法运行的。

里面的内容是可以画出爱心的,用是这个爱心曲线公式:

image.png

然后遍历一个1517的方阵,计算每个坐标是在曲线内还是曲线外,在内部就输出#或,外部就是-

用python改写一下是这样的:

for y inrange(9, -6, -1):

   for x inrange(-8, 9):

       print('*##*'[(x+10)%4] if (x*x+y*y-25)**3 < 25*x*x*y*y*y else'-', end=' ')

   print()

效果:

image.png

稍微改一下输出,还能做出前面那个全是1的效果:

for y inrange(9, -6, -1):

   for x inrange(-8, 9):

       print('1'if (x*x+y*y-25)**3 < 25*x*x*y*y*y else' ', end=' ')

   print()

image.png

但跟剧中所谓的效果相去甚远。

  1. 最后是主角狂拽酷炫D炸天的跳动爱心:

heart2.gif

代码有两个片段:

image.png

image.png

但这两个片段也不C语言,而是C++,且两段并不是同一个程序,用的方法也完全不一样。

第一段代码跟前面一种思路差不多,只不过没有直接用一条曲线,而是上半部用两个圆形,下半部用两条直线,围出一个爱心。

image.png

改写成 Python 代码:

size = 10

for x inrange(size):

   for y inrange(4*size+1):

       dist1 = ((x-size)**2 + (y-size)**2) ** 0.5

       dist2 = ((x-size)**2 + (y-3*size)**2) ** 0.5

       if dist1 < size + 0.5or dist2 < size + 0.5:

           print('V', end=' ')

       else:

           print(' ', end=' ')

   print()

 

for x inrange(1, 2*size):

   for y inrange(x):

       print(' ', end=' ')

   for y inrange(4*size+1-2*x):

       print('V', end=' ')

   print()

运行效果:

image.png

第二段代码用的是基于极坐标的爱心曲线,是遍历角度来计算点的位置。公式是:

image.png

计算出不同角度对应的点坐标,然后把它们连起来,就是一个爱心。

from math import pi, sin, cos

import matplotlib.pyplot as plt

no_pieces = 100

dt = 2*pi/no_pieces

t = 0

vx = []

vy = []

while t <= 2*pi:

   vx.append(16*sin(t)**3)

   vy.append(13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t))

   t += dt

plt.plot(vx, vy)

plt.show()

效果:

image.png

代码中循环时用到的2π是为了保证曲线长度足够绕一个圈,但其实长一点也无所谓,即使 π=100 也不影响显示效果,只是相当于同一条曲线画了很多遍。所以剧中代码里写下35位小数的π,还被女主用纸笔一字不落地抄写下来,实在是让程序员无法理解的迷惑行为。

image.png

但不管写再多位的π,上述两段代码都和最终那个跳动的效果差了五百只羊了个羊。

跳动爱心实现

作为一个总是在写一些没什么乱用的代码的编程博主,Crossin当然也不会放过这个机会,下面就来挑战一下用 Python 实现最终的那个效果。

  1. 想要绘制动态的效果,必定要借助一些库的帮助,不然代码量肯定会让你感动得想哭。这里我们将使用之前 羊了个羊游戏 里用过的 pgzero 库。然后结合最后那个极坐标爱心曲线代码,先绘制出曲线上离散的点。

import pgzrun

from math import pi, sin, cos

 

no_p = 100

dt = 2*3/no_p

t = 0

x = []

y = []

while t <= 2*3:

   x.append(16*sin(t)**3)

   y.append(13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t))

   t += dt

 

defdraw():

   screen.clear()

   for i inrange(len(x)):

       screen.draw.filled_rect(Rect((x[i]*10+400, -y[i]*10+300), (4, 4)), 'pink')

 

pgzrun.go()

image.png

  1. 把点的数量增加,同时沿着原点到每个点的径向加一个随机数,并且这个随机数是按照正态分布来的(半个正态分布),大概率分布在曲线上,向曲线内部递减。这样,就得到这样一个随机分布的爱心效果。

...

no_p = 20000

...

while t <= 2*pi:

   l = 10 - abs(random.gauss(10, 2) - 10)

   x.append(l*16*sin(t)**3)

   y.append(l*(13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t)))

   t += dt

...

image.png

  1. 下面就是让点动起来,这步是关键,也有一点点复杂。为了方便对于每个点进行控制,这里将每个点自定义成了一个Particle类的实例。

从原理上来说,就是给每个点加一个缩放系数,这个系数是根据时间变化的正弦函数,看起来就会像呼吸的节律一样。

classParticle():

   def__init__(self, pos, size, f):

       self.pos = pos

       self.pos0 = pos

       self.size = size

       self.f = f

 

   defdraw(self):

       screen.draw.filled_rect(Rect((10*self.f*self.pos[0] + 400, -10*self.f*self.pos[1] + 300), self.size), 'hot pink')

 

   defupdate(self, t):

       df = 1 + (2 - 1.5) * sin(t * 3) / 8

       self.pos = self.pos0[0] * df, self.pos0[1] * df

 

...

 

t = 0

defdraw():

   screen.clear()

   for p in particles:

       p.draw()

 

defupdate(dt):

   global t

   t += dt

   for p in particles:

       p.update(t)

heart3.gif

  1. 剧中爱心跳动时,靠中间的点波动的幅度更大,有一种扩张的效果。所以再根据每个点距离原点的远近,再加上一个系数,离得越近,系数越大。

classParticle():

   ...

   defupdate(self, t):

       df = 1 + (2 - 1.5 * self.f) * sin(t * 3) / 8

       self.pos = self.pos0[0] * df, self.pos0[1] * df

heart4.gif

  1. 最后再用同样的方法画一个更大一点的爱心,这个爱心不需要跳动,只要每一帧随机绘制就可以了。

defdraw():

   ...

   t = 0

   while t < 2*pi:

       f = random.gauss(1.1, 0.1)

       x = 16*sin(t)**3

       y = 13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t)

       size = (random.uniform(0.5,2.5), random.uniform(0.5,2.5))

       screen.draw.filled_rect(Rect((10*f*x + 400, -10*f*y + 300), size), 'hot pink')

       t += dt * 3

heart5.gif

合在一起,搞定!

heart6.gif

总结一下,就是在原本的基础爱心曲线上加上一个正态分布的随机量、一个随时间变化的正弦函数和一个跟距离成反比的系数,外面再套一层更大的随机爱心,就得到类似剧中的跳动爱心效果。

但话说回来,真有人会在考场上这么干吗?

除非真的是超级大学霸,不然就是食堂伙食太好--

吃太饱撑的……

代码已开源:python666.cn/c/9
如二创发布请注明代码来源:Crossin的编程教室
相关文章
|
2月前
|
移动开发 前端开发 JavaScript
童年回忆——开心消消乐(内含源码inscode一键运行)
童年回忆——开心消消乐(内含源码inscode一键运行)
|
2月前
|
机器人 程序员 C++
Scratch3.0——助力新进程序员理解程序(案例一十一、大象吃苹果)
Scratch3.0——助力新进程序员理解程序(案例一十一、大象吃苹果)
32 0
|
9月前
|
程序员 C语言 C++
电视剧里的代码真能运行吗?
虽然剧中说是“C语言期中考试”,但这位同学的代码名叫 draw2.py,一个典型的 Python 文件,再结合截图中的 pen.forward、pen.setpos 等方法来看,应该是用 turtle 海龟作图库来画爱心。
|
11月前
|
Python
一日一技:你的代码是如何被炫技毁掉的
一日一技:你的代码是如何被炫技毁掉的
76 0
|
程序员 Android开发 iOS开发
程序员五一修图小贴士
程序员五一修图小贴士
121 0
程序员五一修图小贴士
程序人生 - 为什么大人永远不懂孩子的世界?
程序人生 - 为什么大人永远不懂孩子的世界?
92 0
程序人生 - 为什么大人永远不懂孩子的世界?
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(五)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(五)
51 0
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(五)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(三)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(三)
62 0
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(三)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(四)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(四)
53 0
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(四)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(一)
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(一)
74 0
程序人生 - 写完这篇文章后,我被保险公司追杀了几十条街(一)