--im a beginner ..so im not sure how to make sure that the snowflakes don't overlap. Thanks!
import turtle
turtle.right(90)
turtle.penup()
turtle.goto(-700,300)
turtle.pendown()
def snowflakebranch(n):
turtle.forward(n*4)
for i in range(3):
turtle.backward(n)
turtle.right(45)
turtle.forward(n)
turtle.backward(n)
turtle.left(90)
turtle.forward(n)
turtle.backward(n)
turtle.right(45)
def snowflake(n):
for i in range(8):
snowflakebranch(n)
turtle.backward(n)
turtle.right(45)
import random
turtle.colormode(255)
turtle.tracer(0)
for i in range(35):
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
turtle.color(r, g, b)
x = random.randint(-500, 500)
y = random.randint(-500, 500)
d = random.randint(6, 16)
snowflake(d)
turtle.penup()
turtle.goto(x, y)
#turtle.forward(250)
turtle.pendown()
turtle.update()
One approach would be to calculate a bounding rectangle (or circle) for each snowflake. Save these as a list or a set. Whenever you plan to make a new snowflake, first check if its bounding rectangle (or circle) overlaps with the bounds of any previous snowflakes. If it does, don't draw it. If it doesn't, draw it and save its bounds too. An incomplete outline of this approach:
import turtle
import random
def snowflakebranch(n):
turtle.forward(n * 4)
for _ in range(3):
turtle.backward(n)
turtle.right(45)
turtle.forward(n)
turtle.backward(n)
turtle.left(90)
turtle.forward(n)
turtle.backward(n)
turtle.right(45)
def snowflake(n):
for _ in range(8):
snowflakebranch(n)
turtle.backward(n)
turtle.right(45)
def overlapping(bounds_list, bounds):
for previous in bounds_list:
if overlap(previous, bounds):
return True
return False
def overlap(b1, b2):
# return True or False if these two rectanges or circles overlap
pass
turtle.penup()
turtle.colormode(255)
turtle.tracer(0)
previous_bounds = []
i = 0
while i < 35:
x = random.randint(-500, 500)
y = random.randint(-500, 500)
turtle.goto(x, y)
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
turtle.color(r, g, b)
turtle.pendown()
d = random.randint(6, 16)
# work out the bounding rectangle or circle based on 'd', 'x' & 'y'
# e.g. (x, y, width & height) or (x, y, radius)
bounds = ( ... )
if not overlapping(previous_bounds, bounds):
snowflake(d)
turtle.update()
previous_bounds.append(bounds)
i += 1
turtle.penup()
turtle.done()
An image of non-overlapping snowflakes using the above logic with the bounding circles also displayed:
I actually like the look of your overlapping snowflakes. Even if you want overlap, the above logic will allow you to control how much overlap.
Related
I'm trying to use turtle in order to draw a rectangle, and then 32 equal cells inside it. But I somehow can't get it right, I don't know why.
Here is the code I've written:
import turtle, tkinter, datetime, time
turtle.setx(-400)
turtle.sety(200)
turtle.pendown()
turtle.pencolor('#00807c')
for i in range (0,4):
x = 800
if i%2 == 0:
turtle.fd(x)
else:
turtle.fd(x/2)
turtle.right(90)
def cells(position):
for i in range (0,4):
x = 100
turtle.fd(x)
turtle.right(90)
if turtle.pos() == position:
turtle.fd(x)
position = turtle.pos()
for j in range(0, 8):
cells(turtle.pos())
turtle.done()
The result is weird, it only draws three or four cells and then the program ends.
I'd be grateful if somebody could possibly help me with this problem. Thanks.
I've rewritten your code and I don't understand why you're using a function. I've used 3 loops:
loop 3(4):
loop 2(8):
loop 1(4):
The first loop repeats himself 4 times and draws the sides of 1 square
The second loop runs the first loop 8 times, so it draws 8 squares next to each other
The third loop runs the second loop 4 times, so it draws 4 lines of 8 squares.
And that makes a field of 32 cells.
My code:
import turtle, tkinter, datetime, time
turtle.penup()
turtle.hideturtle()
turtle.setx(-400)
turtle.sety(200)
turtle.pendown()
turtle.pencolor('#00807c')
turtle.speed(0)
turtle.pendown()
for i in range (4):
x = 800
if i%2 == 0:
turtle.fd(x)
else:
turtle.fd(x/2)
turtle.right(90)
for w in range (4):
for i in range (8):
for i in range (4):
x = 100
turtle.fd(x)
turtle.right(90)
turtle.forward(x)
turtle.penup()
turtle.goto(-400,turtle.ycor()-100)
turtle.pendown()
turtle.done()
PS: I've also changed a few things like:
I hid the turtle
I changed the speed (to maximum)
I added a turtle.penup()-command before I moved the turtle in the beginning, so you don't see a black line.
Kind regards
spyrolix
You can create two functions, to simplify the logic: One to draw a square, and one to position the turtle at the place to draw a square. Then, using a little bit of index arithmetic in two nested loops (one for rows, and one for columns), use the indices values, and the side length of a square to draw at the correct location:
Maybe like this:
import turtle, tkinter
def draw_square(side):
"""draws a square of side=side starting at the current turtle location
"""
turtle.pendown()
turtle.setheading(0)
for _ in range(4):
turtle.forward(side)
turtle.left(90)
turtle.penup()
def draw_grid(rows, cols):
"""positions the turtle at the correct location,
in order to draw a grid of squares
"""
for jdx in range(rows):
for idx in range(cols):
turtle.penup()
turtle.goto(startx + side*idx, starty + side*jdx)
draw_square(side)
turtle.pencolor('#00807c')
side = 20
startx, starty = 0, 0 # this can be changed,
# other locations used are relative to this starting point
turtle.penup()
turtle.goto(startx, starty)
rows, cols = 4, 8 # this can be changed
draw_grid(rows, cols)
turtle.goto(startx, starty) # return to the starting point
turtle.done()
This is a situation where I would switch from drawing to stamping to simplify the code and speed it up:
from turtle import Screen, Turtle
WIDTH, HEIGHT = 800, 400
SQUARE = 100
CURSOR_SIZE = 20
def cells(t):
x, y = t.position()
for dy in range(HEIGHT // SQUARE):
turtle.goto(x, y + dy * SQUARE)
for dx in range(WIDTH // SQUARE):
turtle.stamp()
turtle.forward(SQUARE)
screen = Screen()
turtle = Turtle()
turtle.hideturtle()
turtle.shape('square')
turtle.shapesize(HEIGHT / CURSOR_SIZE, WIDTH / CURSOR_SIZE)
turtle.color('#00807c', 'white')
turtle.speed('fastest')
turtle.penup()
turtle.stamp() # draw outer perimeter
turtle.shapesize(SQUARE / CURSOR_SIZE)
turtle.goto(SQUARE/2 - WIDTH/2, SQUARE/2 - HEIGHT/2)
cells(turtle) # draw inner squares
screen.exitonclick()
I'd also remove magic numbers from the body of the code and declare them at the start to make them easier to adjust.
I was just wondering on how to get different colors on each line of the hexagon. Below I have the desired output and input.
Output Right Now - Link to output right now
Output I want - Link to output I want
import turtle as trtl
colors = ["#9c2921", "#cf8e04","#f5d905",]
#--------------------
num_sides = int(input("Enter the number of sides(Enter 6 to get the output of the real image): "))
if num_sides == 6:
print("Desired artwork is displayed")
side_length = 25
circumradius = side_length
angle = 360/len(colors)
trtl.width(10)
for color in colors:
trtl.color(color)
trtl.pensize(10)
for move_turtle in range(1):
trtl.penup()
trtl.sety(-circumradius)
trtl.pendown()
trtl.circle(circumradius, steps = num_sides)
circumradius *= 2
trtl.hideturtle()
Oddly, your program looks like code I wrote in response to your previous question that has neither been accepted nor upvoted. Moving on:
Given this circle() and a fat pen based approach for drawing the hexagons, I believe this is about the best you can do:
import turtle
from itertools import cycle
COLORS = ["#9c2921", "#f5d905", "#cf8e04",]
NUM_SIDES = 6
SIDE_LENGTH = 50
PEN_WIDTH = 25
circumradius = SIDE_LENGTH
turtle.width(PEN_WIDTH)
color = cycle(COLORS)
for _ in range(4):
turtle.penup()
turtle.sety(-circumradius)
turtle.pendown()
for _ in range(NUM_SIDES):
turtle.color(next(color))
turtle.circle(circumradius, extent=360/NUM_SIDES, steps=1)
circumradius += PEN_WIDTH*2
turtle.hideturtle()
turtle.done()
To get closer to the target image, you'd need to draw the individual segments of the hexagon (circle) as trapezoids.
import turtle
from itertools import cycle
COLORS = ["#9c2921", "#f5d905", "#cf8e04",]
NUM_SIDES = 6
SIDE_LENGTH = 50
PEN_WIDTH = 30
circumradius = SIDE_LENGTH
turtle.width(1)
turtle.speed('fastest') # because I have no patience
color = cycle(COLORS)
for _ in range(4):
turtle.penup()
turtle.sety(-circumradius)
turtle.pendown()
for _ in range(NUM_SIDES):
turtle.color(next(color))
turtle.circle(circumradius, extent=360/NUM_SIDES, steps=1)
turtle.right(90)
turtle.begin_fill()
turtle.forward(PEN_WIDTH/2)
turtle.right(120)
turtle.forward(circumradius + PEN_WIDTH/2)
turtle.right(120)
turtle.forward(PEN_WIDTH/2)
turtle.end_fill()
turtle.begin_fill()
turtle.forward(PEN_WIDTH/2)
turtle.right(60)
turtle.forward(circumradius - PEN_WIDTH/2)
turtle.right(60)
turtle.forward(PEN_WIDTH/2)
turtle.end_fill()
turtle.left(90)
circumradius += PEN_WIDTH*2
turtle.hideturtle()
turtle.done()
Screenshot of output image
I made a random walk program using turtle and I want it show where the two turtles cross paths by changing the color.
`import turtle as T
import random as R
t = T.Turtle()
u = T.Turtle()
t.speed(0)
u.speed(0)
t.hideturtle()
u.hideturtle()
t.color("red")
u.color("blue")
def randWalk(num):
for i in range(0, num):
x = R.choice((-1,1))
X = R.choice((-1,1))
y = R.choice((-1,1))
Y = R.choice((-1,1))
t.forward(x)
u.forward(X)
if y == 1:
t.left(90)
t.forward(1)
else:
t.right(90)
t.forward(1)
if Y == 1:
u.left(90)
u.forward(1)
else:
u.right(90)
u.forward(1)
randWalk(4000)`
Turtle can't interrogate what color is currently on the screen, so one way to approach this might be to have some sort of backing store where you keep track of what color was written to what pixel. Here's a rough example using Python lists:
from turtle import Screen, Turtle
from random import choice
WIDTH, HEIGHT = 300, 300
PEN_COLORS = ['red', 'blue']
OVERLAP_COLOR = 'green'
def randWalk(number):
for _ in range(number):
for turtle in turtles:
direction = choice((-1, 1))
turtle.forward(direction)
x, y = map(round, turtle.position())
old_color = color = turtle.pencolor()
turtle.undo() # undo forward()
if grid[y][x] and grid[y][x] != color:
color = OVERLAP_COLOR
turtle.pencolor(color)
turtle.goto(x, y) # redo forward()
turtle.pencolor(old_color)
grid[y][x] = color
choice((turtle.left, turtle.right))(90)
screen.update()
screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.tracer(False)
grid = [[None] * WIDTH for _ in range(HEIGHT)]
turtles = []
for color in PEN_COLORS:
turtle = Turtle()
turtle.hideturtle()
turtle.pencolor(color)
turtles.append(turtle)
randWalk(4000)
screen.tracer(True)
screen.exitonclick()
There is additional complication in the code as turtle walks a floating point plane but we need to coerce it to an integer plane to accommodate our backing store and reduce undesirable drawing artifacts.
I am creating a project that loads an image and converts it to 1 and zeros it will then draw this using turtle. However, every time I run it tells me that it has stopped working after the first column has been completed. If the problem is with the processing power of my computer I would like to know if there is a way to switch to a GPU to achieve the task. Any help would be greatly appreciated. Thanks
def ShowMaze(possibleRoutes):
turtle.delay(0)
for x in range(0,len(Maze)):
for y in range(0,len(Maze[0])):
if Maze[x][y]==3:
Maze[x][y]=0
for x in range(0,len(Maze)):
turtle.forward(-5)
turtle.right(90)
turtle.forward(5/len(Maze[0]))
turtle.left(90)
for y in range(0,len(Maze[0])):
if Maze[x][y]==1:
turtle.fillcolor("black")
turtle.begin_fill()
elif Maze[x][y]==0:
turtle.fillcolor("white")
turtle.begin_fill()
elif Maze[x][y]==4:
turtle.fillcolor("green")
turtle.begin_fill()
elif Maze[x][y]==5:
turtle.fillcolor("red")
turtle.begin_fill()
for i in range(0,4):
turtle.forward(5/len(Maze[0]))
turtle.left(90)
turtle.end_fill()
turtle.forward(5/len(Maze[0]))
input()
for ii in range(1,len(possibleRoutes)-1):
turtle.pu()
turtle.home()
turtle.forward(-250)
turtle.forward((250/len(Maze))*possibleRoutes[ii][1])
turtle.right(90)
turtle.forward((250/len(Maze))*possibleRoutes[ii][0]+(250/len(Maze)))
turtle.left(90)
turtle.fillcolor("blue")
turtle.pd()
turtle.begin_fill()
for x in range(0,4):
turtle.forward(250/len(Maze[0]))
turtle.left(90)
turtle.end_fill()
im = Image.open('D:/MazeSolver/ExampleMazePicture.JPG') # Can be many different formats.
pix = im.load()
size=250
Maze=[]
length=im.size[0] # Get the width and hight of the Maze for iterating over
for x in range(0,size,8):
print("Row",x)
row=[]
for y in range(0,size,2):
pix = im.load()
if pix[x,y]>=(200,200,200):
node=0
elif pix[x,y][0]>200 and pix[x,y][2]<200 and pix[x,y][1]<200:
node=4
print("End")
elif pix[x,y][1]>200 and pix[x,y][0]<50 and pix[x,y][2]<50:
node=5
print("Start")
elif pix[x,y]<=(50,50,50):
node=1
else:
print(pix[x,y])
row.append(node)
Maze.append([row])
ShowMaze(Maze)
This code is a mess. You input a JPEG maze image, called Maze, into a two dimensional array and pass it to ShowMaze(Maze) to show that you've read it in correctly. But ShowMaze() accesses Maze globally and thinks its argument is ShowMaze(possibleRoutes) where possibleRoutes through the maze were never calculated? Also: the X and Y sense of Maze seems inverted; the rows of the maze have an extra layer of list wrapped around them for no apparent reason; there's dead code included; you're not reading it in as 1s and 0s but rather four different color codes; the drawing code seems hopeless.
I've reworked your code to simply read the maze into a list of lists and then display it with turtle using stamping instead of drawing to both simplify and speed up the code:
from turtle import Screen, Turtle
from PIL import Image
CURSOR_SIZE = 20
PIXEL_SIZE = 5
COLORS = {0: 'white', 1: 'black', 4: 'green', 5: 'red'}
def ShowMaze(maze):
height, width = len(maze), len(maze[0])
screen = Screen()
screen.setup(width * PIXEL_SIZE, height * PIXEL_SIZE)
screen.setworldcoordinates(0, height, width, 0)
turtle = Turtle('square', visible=False)
turtle.shapesize(PIXEL_SIZE / CURSOR_SIZE)
turtle.penup()
screen.tracer(False)
for y in range(height):
for x in range(width):
color = maze[y][x]
if color in COLORS:
turtle.fillcolor(COLORS[color])
else:
turtle.fillcolor("orange") # error color
turtle.stamp()
turtle.forward(1)
turtle.goto(0, turtle.ycor() + 1)
screen.tracer(True)
screen.mainloop()
image = Image.open('ExampleMazePicture.JPG') # Can be many different formats.
width, height = image.size # Get the width and height of the Maze for iterating over
pixels = image.load()
maze = []
for y in range(0, width, 4):
print("Row:", y)
row = []
for x in range(0, width, 4):
node = -1
pixel = pixels[x, y]
if pixel >= (200, 200, 200):
node = 0
elif pixel[0] > 200 and pixel[1] < 200 and pixel[2] < 200:
node = 4
print("End")
elif pixel[0] < 50 and pixel[1] > 200 and pixel[2] < 50:
node = 5
print("Start")
elif pixel <= (50, 50, 50):
node = 1
else:
print(pixel)
row.append(node)
maze.append(row)
ShowMaze(maze)
Output based on using "Figure 1.6: Picobot’s maze." from this page as input:
Hopefully this should provide you a starting point for the program you're ultimately trying to develop.
I need to make my python code draw my stars in different sizes at random. I've tried every method I know but unable to figure it out...still trying to completely understand loops.
import turtle
import random
for n in range(60):
turtle.penup()
turtle.goto(random.randint(-400, 400), random.randint(-400, 400))
turtle.pendown()
red_amount = random.randint( 0, 100) / 100.0
blue_amount = random.randint(0 , 100) / 100.0
green_amount = random.randint( 0, 100) / 100.0
turtle.pencolor((red_amount, green_amount, blue_amount))
turtle.pensize(random.randint(1, 10))
for i in range(6):
turtle.begin_fill()
turtle.forward(50)
turtle.right(144)
turtle.end_fill()
All it does currently is draw stars at the same size.
You've added code to randomize the color, starting position and pen width but there's none to change the size of the stars. The size is controlled by this statement:
turtle.forward(50)
but you don't want to simply replace the 50 with another call to the random module as your stars will come out irregular. You need to compute a random size before the loop and then use that size in the forward() call in the loop:
import turtle
import random
for n in range(60):
turtle.penup()
turtle.goto(random.randint(-400, 400), random.randint(-400, 400))
turtle.pendown()
red_amount = random.random()
blue_amount = random.random()
green_amount = random.random()
turtle.color(red_amount, green_amount, blue_amount)
turtle.pensize(random.randint(1, 10))
size = random.randint(25, 100)
turtle.begin_fill()
for i in range(5):
turtle.forward(size)
turtle.right(144)
turtle.end_fill()
turtle.done()
I've also made a few style changes to your code while I was at it.