Sierpinski三角形Pygame递归

10

我目前的大学论文要求我们创建一个Sierpinski三角形,并递归地在内部绘制新的三角形。

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

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)

我开始编写这个函数:

  1. 添加退出参数(当三角形变得太小时返回 false)
  2. 如果三角形不太小,则用白色绘制第一个三角形
  3. 之后在相同的 x 位置但 y 坐标减半的地方,用黑色绘制一个倒置的一半大小的三角形(这创造了三角形错觉)
  4. 最后进行4次递归调用,经过实验,我知道这些调用的顺序很重要,因为改变它们会导致输出发生巨大变化。

目前的输出如下所示:

Sierpinski's Triangle Pygame Recursive

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

谢谢!


这让我想起我早期用pygame编写的一个脚本,使用混沌游戏技术绘制了一颗Sierpinski三角形。 - elParaguayo
1个回答

4
请查看下面的链接,它实现了Sierpinski三角形...

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

很好的讨论和40多行代码来实现它。此外,由于海龟模块的工作方式,您可以逐个观看每个三角形的绘制过程。这对于您回顾代码非常有帮助,因为您可以可视化递归的级别以及它们发生的时间。我不知道在pygame中实现这个会有多难,但如果您可以减慢三角形的创建速度,那么理解逻辑就更容易了。
您说您需要基于实验的4个递归调用,但您能解释一下背后的逻辑吗?直觉上,这似乎是错误的,因为您只需要三个新三角形加上一个部分覆盖的父级即可等于四个较小的等边三角形。(请参见链接中的操作?)
您能解释一下为什么要使用倒三角形方法吗?这似乎有点像易错的解决方法?您应该能够使用正常三角形函数的负空间来绘制倒三角形。在链接中,您将看到作者绘制了一个面向与其他所有东西相同方向的绿色三角形,但稍后用更多的三角形覆盖它,直到绿色三角形面向相反的方向。
总的来说,看起来您很接近了。您只需要正确地理解最后一部分递归逻辑即可。
附言。
一点小的样式批评 - 只是因为这是用Python编写的,可读性很重要。您可以使用 While True 然后 break 来避免额外的变量 done

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接