编程小实验:利用随机数生成分形

前言

作为我发的第一篇博客,当然要先出点干货。最近听哥哥讲,他在知乎上面看到了一个利用随机数生成分形的实验。不久前我用Python的简单绘图库PyGame就做了一下这个实验,还真的可以呀!于是就打算分享一下。

 

算法

这个实验的核心是如下的算法:

取三点A,B,C于同一直线,又取线外另一动点D。那么,程序不停地执行,每一轮进行如下操作:

  1. 生成一个介于1 ~ 6之间的随机整数。
  2. 随机数如果是1或2,我们选择点A进行下一步;如果是3或4,选择点B;如果是5或6,选择点C。
  3. 将点D的新位置设为点D与在上一步选中的点的中点(纵横坐标分别设为该两点的纵横坐标平均值)。

在执行了若干次上述的操作之后,点D曾经的所有位置将形成一张分形图。

真的有那么神奇吗?接下来就试一试。

 

实现

既然这样,需要些什么东西呢?

  1. 定义一个方便每一轮调用的算法函数。
  2. 定义一个保证绘图窗口正常运行的条件循环(如果尚不清楚PyGame工作原理,请参考PyGame入门
  3. 定义一个一次绘制完全部点的函数。

确保已经安装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)

然后调试一下:

哈哈哈,有点意思。

一直在琢磨这是什么规律,没搞懂,还在想。

结语

第一次写博客,体验到与人分享之乐。当然也有不足,我会慢慢纠正。欢迎留言指出错误,也可以让我们一起讨论这个算法的规律。

经常找些“奇怪”的实验项目玩一玩,你会发现很多东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值