前言
作为我发的第一篇博客,当然要先出点干货。最近听哥哥讲,他在知乎上面看到了一个利用随机数生成分形的实验。不久前我用Python的简单绘图库PyGame就做了一下这个实验,还真的可以呀!于是就打算分享一下。
算法
这个实验的核心是如下的算法:
取三点A,B,C于同一直线,又取线外另一动点D。那么,程序不停地执行,每一轮进行如下操作:
- 生成一个介于1 ~ 6之间的随机整数。
- 随机数如果是1或2,我们选择点A进行下一步;如果是3或4,选择点B;如果是5或6,选择点C。
- 将点D的新位置设为点D与在上一步选中的点的中点(纵横坐标分别设为该两点的纵横坐标平均值)。
在执行了若干次上述的操作之后,点D曾经的所有位置将形成一张分形图。
真的有那么神奇吗?接下来就试一试。
实现
既然这样,需要些什么东西呢?
- 定义一个方便每一轮调用的算法函数。
- 定义一个保证绘图窗口正常运行的条件循环(如果尚不清楚PyGame工作原理,请参考PyGame入门)
- 定义一个一次绘制完全部点的函数。
确保已经安装PyGame。
在这里说明一下——我们绘制三种颜色的点:
- 红色:A、B、C三个基准点
- 黄色:当前活动的动点D
- 绿色:动点D曾经的位置
好了,先上第一次完工的代码:
import pygame
from random import randint
dic = ['A', 'A', 'B', 'B', 'C', 'C']
# define 3 points on the same line
A = (200, 300)
B = (500 * 2, 500 * 2)
C = (800 * 2, 300 * 2)
const = [100, 500]# the rect of the screen
D = const[:]
N = 500
points = [D[:]]
count = 0
rect = [1200, 700]# this rect is for non-fullscreen debugging mode
def do():# action in every loop
rdt = randint(1, 6)
print(rdt)
point = eval(dic[rdt - 1])
global D
D = [abs(point[0] - D[0]) // 2, abs(point[1] - D[1]) // 2]
if D[0] < 0 or D[0] > rect[0] or D[1] < 0 or D[1] > rect[1]: D = const[:]
points.append(D[:])
def draw_pnt():# draw the points
for i in points:
pygame.draw.circle(GUI, [0, 255, 0], i, 1)
pygame.draw.circle(GUI, [255, 0, 0], A, 1)
pygame.draw.circle(GUI, [255, 0, 0], B, 1)
pygame.draw.circle(GUI, [255, 0, 0], C, 1)
pygame.draw.circle(GUI, [255, 255, 0], D, 1)
print(points)
GUI = pygame.display.set_mode(rect, pygame.FULLSCREEN)# show on a full screen
running = True
while running:
count += 1# a counter
print(count)
GUI.fill([0, 0, 0])# fill the screen
do()
draw_pnt()
pygame.display.flip()
for evt in pygame.event.get():
if evt.type == pygame.QUIT:
running = False
pygame.quit()
(代码有不当之处请见谅)
不难看出,程序分为几个简单的部分,第一部分定义常量,第二部分定义函数,第三部分执行程序。
经过多次修正后,A,B,C三点的位置比较适合了。
我们准备调试。注意:可以按下Windows键退出全屏模式。
执行上面的代码几分钟后,可以得到下面的图案:
虽然似乎只看见一个小红点,和一大堆绿绿的组成图案的东东……但是已经可以看到一个明显的分形图了!
再换另一图案试试?将上面的三行
A = (200, 300)
B = (500 * 2, 500 * 2)
C = (800 * 2, 300 * 2)
修改为:
A = (200, 300)
B = (1000, 600)
C = (1800, 900)
然后调试一下:
哈哈哈,有点意思。
一直在琢磨这是什么规律,没搞懂,还在想。
结语
第一次写博客,体验到与人分享之乐。当然也有不足,我会慢慢纠正。欢迎留言指出错误,也可以让我们一起讨论这个算法的规律。
经常找些“奇怪”的实验项目玩一玩,你会发现很多东西。