谢尔宾斯基三角 Pygame 递归

Posted

技术标签:

【中文标题】谢尔宾斯基三角 Pygame 递归【英文标题】:Sierpinski's Triangle Pygame Recursive 【发布时间】:2015-10-24 23:37:27 【问题描述】:

因此,对于我目前的大学论文,我们打算创建一个 Sierpinksi 三角形并在其中递归地绘制新三角形。

我们得到的原始代码是这样的:

import sys, pygame

# a function that will draw a right-angled triangle of a given size anchored at a given location
def draw_triangle(screen, x, y, size):
        pygame.draw.polygon(screen,white,[[x,y], [x+size,y], [x,y-size]])

############################################################################################# 
# Define a function that will draw Sierpinski's Triangle at a given size anchored at a given location
# You need to update this function 
# currently only one triangle is drawn

def sierpinski(screen, x, y, size):
        draw_triangle(screen, x, y, size)

############################################################################################# 

# Initialize the game engine
pygame.init()

# Define the colors we will use in RGB format
black = [ 0, 0, 0]
white = [255,255,255]
blue = [ 0, 0,255]
green = [ 0,255, 0]
red = [255, 0, 0]

# Set the height and width of the screen
size=[512, 512]
screen=pygame.display.set_mode(size)

# Loop until the user clicks the close button.
done=False
clock = pygame.time.Clock()


while done==False:

    # This limits the while loop to a max of 10 times per second.
    # Leave this out and we will use all CPU we can.
    clock.tick(10)

    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT: # If user clicked close
            done=True # Flag that we are done so we exit this loop

    # Clear the screen and set the screen background
    screen.fill(black)

    # Draw Sierpinski's triangle at a given size anchored at a given location

    sierpinski(screen,0, 512, 512)

    # Go ahead and update the screen with what we've drawn.
    # This MUST happen after all the other drawing commands.
    pygame.display.flip()

# Tidy up
pygame.quit ()

好的,我知道这只会创建一个三角形。这是我为使其“有点”工作所做的:

我创建了一个新的三角形函数来绘制一个倒三角形:

def draw_upside_down_triangle(screen, x, y, size, color):
        pygame.draw.polygon(screen, color, [[x+size, y+size], [x+size, y], [x, y]])

然后我更新了旧的三角形函数以接受颜色变量:

def draw_triangle(screen, x, y, size, color):
        pygame.draw.polygon(screen, color, [[x, y], [x+size, y], [x, y-size]])

之后我更新了递归绘制三角形的主函数:

def sierpinski(screen, x, y, size):
    if size < 10:
        return False
    else:
        draw_triangle(screen, x, y, size, white)
        draw_upside_down_triangle(screen, x, y/2, size/2, black)
        sierpinski(screen, x+size/2, y+size/2, size/2)
        sierpinski(screen, x, y-size/2, size/2)
        sierpinski(screen, x, y, size/2)
        sierpinski(screen, x, y+size/2, size/2)

我关闭了这个功能

    通过添加exit参数(当三角形get太小返回false) 如果不是太小,则用白色绘制第一个三角形 然后在相同的 x 位置绘制一个大小为一半但 y 位置为 黑色 的倒置三角形(这会产生 3 个三角形错觉) 毕竟我有 4 个递归调用,根据实验,我知道这些调用的顺序很重要,因为输出在更改时会发生根本变化。

目前输出如下:

我并不是要求任何人完成或更正我的代码,只是为了更好地理解或指出正确的方向。已经和这个战斗了几个小时了。

谢谢!

【问题讨论】:

让我想起了我早期的一个 pygame 脚本,其中我使用chaos game 技术绘制了一个谢尔宾斯基三角形。 【参考方案1】:

看看下面实现谢尔宾斯基三角形的链接...

http://interactivepython.org/runestone/static/pythonds/Recursion/graphical.html#sierpinski-triangle

围绕这个问题进行了很多很好的讨论,以及 40 行代码来实现它。

另外,由于海龟模块的工作方式,您可以看到每个三角形被一一绘制。这在您查看代码时非常有用,因为您可以可视化递归级别以及它们何时发生。我不知道这在 pygame 中实现起来有多难,但是如果你可以减慢三角形的创建速度,那么理解逻辑就会容易得多。

你说你需要基于实验的 4 个递归调用,但你能解释一下它背后的逻辑吗?直觉上这似乎是错误的,因为您只需要三个新三角形加上一个部分覆盖的父三角形就等于四个较小的等边三角形。 (在链接中查看这是如何完成的?)

您能解释一下为什么要使用倒三角形法吗?这似乎有点像一个容易出错的工作?您应该能够使用正常三角形函数中的负空间来绘制倒置三角形。在链接中,您会看到作者绘制了一个绿色三角形,朝向与其他所有物体相同的方向,但后来用更多三角形覆盖它,直到绿色朝向相反方向。

总而言之,看起来你很接近。您只需要正确处理最后一段递归逻辑即可。

附言

一个次要的次要风格批评 - 仅因为这是用 python 编写的并且可读性很重要。您可以使用While True,然后使用break 来避免额外的变量done

【讨论】:

感谢您的帮助!这是朝着正确方向迈出的一步,但还没有完全完成。我将整个脚本恢复为提供的原始脚本,然后将颜色参数添加到三角形函数中。我通过使用与以前相同的中断情况修改了主函数,并添加了一些新逻辑来首先绘制一个基本三角形,然后是 3 个子三角形,之后我递归调用该函数 3 次以在这 3 个子三角形中绘制三角形。我将代码粘贴在pastebin 问题是左上角的第一个三角形现在没有打印出来。 PS主要循环功能是教授提供的,所以我不会去改变他们没有标记的任何东西,但感谢您的提醒:)

以上是关于谢尔宾斯基三角 Pygame 递归的主要内容,如果未能解决你的问题,请参考以下文章

谢尔宾斯基地毯三角形,周长,面积的变化规律

瓦茨瓦夫·谢尔宾斯基的生平

课时22:函数:递归是神马

Python基础——递归及其经典例题(阶乘斐波那契数列汉诺塔)

Python基础——递归及其经典例题(阶乘斐波那契数列汉诺塔)

使用 OpenGL 绘制谢尔宾斯基时遇到问题