如何防止python中的随机绘图重叠

wyyhbhjk  于 2022-12-02  发布在  Python
关注(0)|答案(1)|浏览(244)

所以,我写了一段代码,用turtle来创建雪花。基本上,它会问用户要生成多少雪花。然后它打开一个turtle窗口,在一个随机的地方画雪花,大小和颜色。随机的地方对这个问题很重要。基本上,当它画雪花时,有没有办法阻止雪花被画在(大致)相同的区域,使它们不重叠?
通常是的,这将是简单的,但由于它的随机性质,我不知道如何做到这一点。以下是代码:

import time
import sys
import turtle
import random

restart = True

print("This program creates snowflakes. Enjoy!")

while restart == True:
 n = int(input("How many snowflakes do you want?: "))
 screen = turtle.Screen()
 screen.bgcolor("black")

 speedy = turtle.Turtle()
 speedy.speed(0)

 sfcolor = ["yellow","gold","orange","red","violet","magenta","purple","navy","blue","skyblue","cyan","turquoise","lightgreen","green","darkgreen","white","BlueViolet","DeepSkyBlue","snow2","ForestGreen", "gainsboro", "GhostWhite", "goldenrod"]

 def snowflake(size):
   speedy.penup()
   speedy.forward(10 * size)
   speedy.left(45)
   speedy.pendown()
   speedy.color(random.choice(sfcolor))
   for i in range(8):
     branch(size)  
     speedy.left(45)
   
 def branch(size):
   for i in range(3):
     for i in range(3):
       speedy.forward(10.0 * size / 3)
       speedy.back(10.0 * size / 3)
       speedy.right(45)
     speedy.left(90)
     speedy.back(10.0 * size / 3)
     speedy.left(45)
   speedy.right(90)
   speedy.forward(10.0 * size)

 for i in range(n):
   x = random.randint(-375, 375)
   y = random.randint(-375, 375)
   sfsize = random.randint(1, 4)
   speedy.penup()
   speedy.goto(x, y)
   speedy.pendown()
   snowflake(sfsize)
   print(i+1," Snowflake(s)")

 restart = False

 print("Thanks for using the program! You will have the option to resart it shortly.")
 time.sleep(3)

 restart = input("Do you want to run the program again? Yes or No: ")
 restart = restart.upper()

 if restart == "YES":
   turtle.Screen().bye()
   restart = True
   print("Restarting...")

 elif restart == "NO":
   restart = False
   print("Thank you for using the program. Goodbye!")
   time.sleep(3)
   turtle.Screen().bye()
   sys.exit()

 else:
   print("\nError. Program Resetting...")
   turtle.Screen().bye()
   print("This program creates snowflakes. Enjoy!")
   restart = True
up9lanfz

up9lanfz1#

类似于@mx0的建议(+1),我们定义了一个包围雪花的圆,而不是一个正方形。对于每一个成功的放置,我们都保留了一个现有位置和半径的列表。我们还使用半径来避免在窗口边缘附近绘制部分雪花:

from turtle import Screen, Turtle
from random import randint, choice

WIDTH, HEIGHT = 480, 320  # small for testing

SF_COLORS = [
    'yellow', 'gold', 'orange', 'red', 'violet',
    'magenta', 'purple', 'navy', 'blue', 'skyblue',
    'cyan', 'turquoise', 'lightgreen', 'green', 'darkgreen',
    'white', 'BlueViolet', 'DeepSkyBlue', 'snow2', 'ForestGreen',
    'gainsboro', 'GhostWhite', 'goldenrod',
]

def snowflake(size):
    radius = 15 * size  # circle roughly encompassing snowflake

    position = randint(radius - WIDTH/2, WIDTH/2 - radius), randint(radius - HEIGHT/2, HEIGHT/2 - radius)
    speedy.goto(position)

    trys = 0

    while any(speedy.distance(other_position) < (radius + other_radius) for other_position, other_radius in snowflakes):
        position = randint(radius - WIDTH/2, WIDTH/2 - radius), randint(radius - HEIGHT/2, HEIGHT/2 - radius)
        speedy.goto(position)

        trys += 1

        if trys > 100:
            return False  # can't fit this snowflake, signal caller to try a different `size`

    snowflakes.append((position, radius))
    speedy.color(choice(SF_COLORS))

    speedy.penup()
    speedy.forward(10 * size)
    speedy.left(45)
    speedy.pendown()

    for _ in range(8):
        branch(size)
        speedy.left(45)

    speedy.penup()

    return True

def branch(size):
    length = 10.0 * size / 3

    for _ in range(3):
        for _ in range(3):
            speedy.forward(length)
            speedy.backward(length)
            speedy.right(45)

        speedy.left(90)
        speedy.backward(length)
        speedy.left(45)

    speedy.right(90)
    speedy.forward(length * 3)

print("This program creates snowflakes. Enjoy!")

n = int(input("How many snowflakes do you want?: "))

screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.bgcolor('black')

speedy = Turtle()
speedy.speed('fastest')

snowflakes = []

flakes = 0

while flakes < n:
    sfsize = randint(1, 4)

    if snowflake(sfsize):
        flakes += 1

speedy.hideturtle()
screen.exitonclick()

然而,像这样调整雪花会产生一个问题。用户可能会请求更多的雪花,而不是在一个给定大小的窗口中。上面的代码通过返回失败并让调用者决定该怎么做来部分解决这个问题。在这里,我们只是尝试另一个雪花大小。更聪明的代码会根据失败来减少随机大小范围,并在1大小的雪花失败时完全停止尝试!

我已经删除了重新启动逻辑,以简化我的示例,因为我不相信它的工作。

相关问题