turtle递归作图绘制谢尔宾斯基地毯【详解】

turtle递归作图绘制谢尔宾斯基地毯【详解】python数据结构与算法turtle递归作图绘制谢尔宾斯基地毯

大家好,又见面了,我是你们的朋友全栈君。

了解谢尔宾斯基地毯

我们先从谢尔宾斯基三角形讲起:
谢尔宾斯基三角形(英语:Sierpinski triangle)是一种分形,由波兰数学家谢尔宾斯基在1915年提出。它是自相似集的例子。
以下是0到3阶的谢尔宾斯基三角形:
在这里插入图片描述

它的构造方法是:
1.取一个实心的等边三角形
2.沿三边中点的连线,将它分成四个小三角形。
3.去掉中间的那一个小三角形。
4.对其余三个小三角形重复(1,2,3)过程。

谢尔宾斯基三角形特点:
容易看出,假设0阶谢尔宾斯基三角形面积为a,周长为b,
那么n阶谢尔宾斯基三角形面积为:a*[(3/4)^n]
周长为:b*[(3/2)^n]
也就是说,当区域无穷大时,我们得到了一个面积为0,但周长却为无穷大的图形。

我们再来看谢尔宾斯基地毯,它的基本图形为一个正方形,然后每次挖去中心的一个小正方形,
直接上图:
在这里插入图片描述

海龟作图turtle

python2.6版本中后引入的一个简单的绘图工具,叫做海龟绘图(Turtle Graphics),出现在1966年的Logo计算机语言。
海龟绘图(turtle库)是python的内部模块,使用前导入即可 import turtle
详细用法这里不具体介绍,可以参考下面这篇文章:
python之turtle海龟绘图篇

代码思路:

我们从最简单的情况想起:一阶地毯
我们将大正方形(先假设边长为3a)放在一个直角坐标系中,左下顶点定为(0,0),右上顶点定为
(3a,3a)
那么容易得到:要挖去那一个小三角形,它的左下顶点坐标为(a,a),边长为a
也即:要挖去的区域为{(x,y)|a<=x<=2a,a<=y<=2a}

那么对于n阶的地毯,我们需要考虑的就是不断减小问题规模,使之回到最简单的情况。

使用代码实现时,我们可以考虑:
对于n阶的谢尔宾斯基地毯,我们先将最大的正方形固定在坐标轴上,
然后考虑每一个最小的正方形是否应该挖去,
例如三阶地毯,设最大正方形面积为9*9=81,那么我们只需要考虑每个面积为1的小正方形应该留下或挖去。
下面上代码:

代码

海龟图画谢尔宾斯基地毯
思路:令最小的一个正方形边长为base,则n阶地毯的边长为base*(3**n)
由于turtle画布的长度为600左右,第一象限长度为300左右,我们令base=int(300/(3^n)
判断每一个边长为base的小正方形是否应该挖去

绘制最外围的正方形:

import turtle

# 画好最外围的正方形,背景设为蓝色
n = int(input())
t = turtle.Turtle()
base = int(300 / (3 ** n))  # 设置每个小正方形长度base
length = base * (3 ** n)  # 最外围的正方形长度
t.pensize(0.1)
turtle.tracer(False)  # 画图过程太长我们跳过不看
t.pencolor('blue')
t.fillcolor('blue')
t.begin_fill()  # 填充蓝色
for i in range(1, 5):
    t.forward(length)
    t.left(90)
t.end_fill()
turtle.done()

运行结果是这样的:
在这里插入图片描述

对于每个边长为base的小正方形,是否应该挖去,需要用到递归:

    def check(n, x, y):  # 判断对于坐标(x,y),判断该处的小正方形是否需要被挖掉,需要则返回False
        if n <= base:  # 结束条件
            return True
        n2 = n // 3
        if n2 <= x < n2 * 2 and n2 <= y < n2 * 2:  # 小正方形处于大正方形中央应该满足的条件
            return False
        return check(n2, x % n2, y % n2)  # 不处于中央的点,递归至下一层的小正方形
        # 取余的操作可以理解为将零点移至小正方形的左下角顶点

最后我们将所有判断为False的小正方形挖去:

    for y in range(0, N, base):
        for x in range(0, N, base):
            if check(N, x, y):
                continue
            else:            # 将(x,y)处小正方形填为空白
                t.penup()
                t.setx(x)
                t.sety(y)
                t.pendown()
                t.pensize(0.1)
                t.pencolor('white')
                t.fillcolor('white')
                t.begin_fill()
                for i in range(1, 5):
                    t.forward(base)
                    t.left(90)
                t.end_fill()
                t.penup()

不要忘了输入和输出:

n = int(input())
carpet(length)

最后完整代码是这样的:

import turtle
n = int(input())
# 画好最外围的正方形,背景设为蓝色
t = turtle.Turtle()
base = int(300 / (3 ** n))  # 设置每个小正方形长度base
length = base * (3 ** n)  # 最外围的正方形长度
t.pensize(0.1)
turtle.tracer(False)  # 画图过程太长我们跳过不看
t.pencolor('blue')
t.fillcolor('blue')
t.begin_fill()  # 填充蓝色
for i in range(1, 5):
    t.forward(length)
    t.left(90)
t.end_fill()



def carpet(N):  # 对于点a(x,y),我们令a点位小正方形的左下角顶点
    def check(n, x, y):  # 判断对于坐标(x,y),判断该处的小正方形是否需要被挖掉,需要则返回False
        if n <= base:  # 结束条件
            return True
        n2 = n // 3
        if n2 <= x < n2 * 2 and n2 <= y < n2 * 2:  # 小正方形处于大正方形中央应该满足的条件
            return False
        return check(n2, x % n2, y % n2)  # 不处于中央的点,递归至下一层的小正方形
        # 取余的操作可以理解为将零点移至小正方形的左下角顶点

    for y in range(0, N, base):
        for x in range(0, N, base):
            if check(N, x, y):
                continue
            else:            # 将(x,y)处小正方形填为空白
                t.penup()
                t.setx(x)
                t.sety(y)
                t.pendown()
                t.pensize(0.1)
                t.pencolor('white')
                t.fillcolor('white')
                t.begin_fill()
                for i in range(1, 5):
                    t.forward(base)
                    t.left(90)
                t.end_fill()
                t.penup()


carpet(length)
turtle.done()

运行结果:
以下依次为n=1~5的n阶谢尔宾斯基地毯:
绘制5阶地毯需要很长时间,因此不继续绘制6阶了
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

参考资料

python数据结构与算法课程 pku陈斌

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158424.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Windows + Linux 双系统的安装

    Windows + Linux 双系统的安装Windows+Linux双系统的安装参考自https://blog.csdn.net/flyyufenfei/article/details/79187656参考自https://blog.csdn.net/u012052268/article/details/77145427文章目录Windows+Linux双系统的安装1.准备工作1.1U盘启动盘的制作1.2分配磁…

    2022年7月24日
    13
  • json格式的字符串是什么类型的_输入字符串的格式要求

    json格式的字符串是什么类型的_输入字符串的格式要求1.JSON数值({“key”:value}){“key”:520,”key1″:1314}2.JSON字符串({“key”:“value”}){“key”:”我爱你”,”key1″:”一生一世”}3.JSON数组({“key”:[value]}){“key”:[520,1314],”key1″:[520,3344]}4.JSON对象({“key”:{value}}

    2022年4月19日
    57
  • 鸿蒙三部曲为什么不写第四部,“鸿蒙三部曲”比“斗罗四作”评分高,为何动画人气远远不如?…

    鸿蒙三部曲为什么不写第四部,“鸿蒙三部曲”比“斗罗四作”评分高,为何动画人气远远不如?…“鸿蒙三部曲”与“斗罗四作”相信熟悉玄幻小说的朋友对于“鸿蒙三部曲”比“斗罗四作”是哪几部就很熟悉了,但更多的是熟悉“斗罗四作”,《斗罗大陆》、《斗罗大陆2:绝世唐门》、《斗罗大陆3:龙王传说》、《斗罗大陆4:终极斗罗》,出自大神作家唐家三少之手。对于“鸿蒙三部曲”就很陌生了,这三部曲分别是:《盘龙》、《星辰变》、《吞噬星空》。这三部小说同样出自大神作家,我爱吃西红柿之手。在2008年的时候,“鸿…

    2022年6月16日
    119
  • 【笔记】ES6 模板字符串

    【笔记】ES6 模板字符串ES6中的字符串可以用反引号括起来用作模板字符串。conststr=`HelloWorld`console.log(str)//HelloWorld通过上面的例子,我们能感觉到,这个用反引号括起来跟单引号括起来貌似没有什么区别,那我们为什么要用模板字符串呢?那是因为我们还没有讲到模板字符串的特性。模板字符串内可以插入变量值和表达式//插入变量constmoon=’月亮’conststr1=`代表${moon}消灭你`console.log(str1)/.

    2022年8月21日
    26
  • 一分钟详解「手眼标定」基本原理[通俗易懂]

    一分钟详解「手眼标定」基本原理[通俗易懂]原文首发于微信公众号【视觉IMAX】。一前言机器人的视觉系统分为固定场景视觉系统和运动的「手-眼」视觉系统。摄像机与机器人的手部末端,构成手眼视觉系统。根据摄像机与机器人相互位置的不同,手眼视觉系统分为Eye-in-Hand系统和Eye-to-Hand系统。Eye-in-Hand系统的摄像机安装在机器人手部末端(end-effector),在机器人工作过程中随机器人一起运动。Eye-to-…

    2022年5月5日
    172
  • keil5如何生成bin文件_怎样创建一个文件夹

    keil5如何生成bin文件_怎样创建一个文件夹原因我碰到原因就是SCT加载文件的问题,我定义了不少段,所以导致bin文件变成了文件夹一般的Bin生成方法:在USER里面Run#1加上$K\ARM\ARMCC\bin\fromelf.exe–bin-o”$L@L.bin””#L”,生成错误出现文件夹,如果没有自定义SCT文件就可使用这种方法解决方法Keil里面的fromelf帮助,可以去看看bincombined_base与你自己的起始地址有关,$K\ARM\ARMCC\bin\fromelf.exe–bincombine

    2022年10月8日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号