递归应用之谢尔宾斯基三角形Python

2020-11-26 10:28发布

递归应用之谢尔宾斯基三角形

谢尔宾斯基三角形,就是在一个三角形中挖掉由每条边重点组成的三角形,进而继续再新生成的三个小三角形中继续挖,如此循环。可以想象,如果无线挖下去,极限情况下,最终整个图形周长是正无穷的,面积为0。当然,也可以是立体三维图像,挖掉由每个面的中心组成的三棱锥,这样极限情况下,面积为正无穷,体积为0。

谢尔宾斯基三角形如图所示。这是一个五阶的。零阶的就是一个三角形,一阶的就是挖掉一个三角形。
谢尔宾斯基三角形
其实最开始我是做不出来这道题的,看了教程,看懂了源代码。换种思路想,与其说挖掉一个三角形,不如说是用三个小三角形按照品字形组成一个大的三角形。那么这样的话,最基本的就是画三角形。需需要用到turtle库,三角形直接根据三个点的坐标绘制即可。这里传入字典,字典的key就是顶点,左边点和右边点,每个坐标就是一个元组,代表x和y。

''
例如'
points = {'left':(-200, -100),
          'top':(0, 200),
          'right':(200, -100)}
'''
def drawTriangle(points):
    t.penup()
    t.goto(points['top'])
    t.pendown()
    t.goto(points['left'])
    t.goto(points['right'])
    t.goto(points['top'])12345678910111213

那么接下来如何做呢?想一想只是一阶的三角形,也就是只需要画出三个小三角形即可。(当然小三角形的坐标是根据大三角形的坐标计算出来的,所以必须需要大三角形).不难看出,小三角形的坐标就是大三角形的三个点的中点,所以需要计算中点。这里传入两个点计算。

def getMid(p1, p2):
    return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2)12

接着继续看一阶的三角形,调用三次画三角形函数即可。

def bigTriangle(points):
	# 画最上方的三角形,需要计算坐标,不难发现,顶点就是原顶点,左边点就是原顶点和原左点的中点,右点同理。传入字典即可
	drawTriangle({
				'top':points['top'],
				'left':getMid(points['left'], points['top']),
				right:getMid(points['top'], points['right'])
				})
	# 画左边的三角形,点的坐标计算同理
	drawTriangle({
				'top':getMid(points['left'], points['top']),
				'left':points['left'],
				right:getMid(points['left'], points['right'])
				})
	# 画右边的三角形
	drawTriangle({
				'top':getMid(points['top'], points['right']),
				'left':getMid(points['left'], points['right']),
				right:points['right']
				})12345678910111213141516171819

那么二阶的呢?三阶的呢?不可能枚举所有的三角形。可以看出来,二阶的就是继续再新生成的小三角形里继续,也就是把新的小三角形当做零阶的继续做,三阶的同样如此,这样明显就可以用递归了。那么什么时候才画三角形呢 ?看一阶的例子,因为三个小三角形不用再挖了,所以就画了,也就是如果是0阶,那就直接画。那么如何判断当前是几阶呢,这样就需要传入一个新的参数,表示阶数,判断当前是否为0阶。

def bigTriangles(degree, points):
	# degree为阶数,如果是0阶那就直接画,否则的话,进行递归更小一阶的三角形
	if degree > 0:
		# 递归上三角形
		bigTriangles(degree - 1, 
					{ 'top':points['top'],
						'left':getMid(points['left'], points['top']),
						'right':getMid(points['top'], points['right'])})
		# 递归左三角形
		bigTriangles(degree - 1, 
					{ 'top':getMid(points['left'], points['top']),
						'left':points['left'],
						'right':getMid(points['left'], points['right'])})
		# 递归右三角形
		bigTriangles(degree - 1, 
					{ 'top':getMid(points['right'], points['top']),
						'left':getMid(points['left'], points['right']),
						'right':points['right']})
	else:
		# 否则此时为0阶,直接画三角形
		drawTriangle(points)123456789101112131415161718192021

测试代码:

import turtle

t = turtle.Turtle()
points = {'left':(-200, -100),
          'top':(0, 200),
          'right':(200, -100)}

bigTriangles(5, points)

turtle.done()



作者:qq_42907161

链接:https://blog.csdn.net/qq_42907161/article/details/108222091

来源:CSDN
著作权归作者所有,转载请联系作者获得授权,切勿私自转载。