How can I create separate coins in a page that are not overlapping or not touching each other. The code below shows overlapping coins if the number is greater than 2.
import turtle
tegan = turtle.Turtle()
turtle.fillcolor('grey')
turtle.begin_fill()
numbers = int(input("How many 50 pence coins you have: "))
print(numbers)
length = 100
degrees = 51.42857
angle = 40
def draw_heptagon(tegan, length, numbers, angle):
for i in range(numbers):
for x in range(7):
turtle.forward(length)
turtle.left(degrees)
turtle.right(angle)
draw_heptagon(tegan, length, numbers, angle)
turtle.end_fill()
turtle.done()
Here's an approximate approach that you can refine. We'll keep track of the centers of the randomly placed heptagons we draw. We'll treat them as circles for purposes of drawing and checking the distances between them:
from turtle import Screen, Turtle
from random import randint
RADIUS = 100
ANGLE = 40
number = int(input("How many 50 pence coins you have: "))
def draw_heptagons(t, number):
coins = []
for _ in range(number):
while True:
x = randint(RADIUS - width/2, width/2 - RADIUS)
y = randint(RADIUS - height/2, height/2 - RADIUS)
t.goto(x, y)
t.right(ANGLE)
if coins and any(t.distance(position) < RADIUS * 2 for position in coins):
continue
break
t.right(90)
t.forward(RADIUS) # draw heptagon centered at x, y
t.left(90)
turtle.begin_fill()
t.circle(RADIUS, steps=7)
turtle.end_fill()
coins.append((x, y))
screen = Screen()
width, height = screen.window_width(), screen.window_height()
turtle = Turtle()
turtle.speed('fastest') # because I have no patience
turtle.penup()
draw_heptagons(turtle, number)
turtle.hideturtle()
screen.exitonclick()
This does what you describe but the heptagons could actually be closer (fit more of them in the window) than circles, so you need to modify the test, and what information you store in positions, if you want to pack them tighter:
Related
import turtle
def main():
t=turtle
s=int(input("Enter the length of each square: "))
t.screensize(2000,2000,"lightblue")
for row in range(0,5):
for column in range(0,5):
if (row+column)%2==0:
t.pendown()
t.fillcolor("black")
t.begin_fill()
square(s,row,column)
else:
t.pendown()
t.fillcolor("white")
t.begin_fill()
square(s,row,column)
t.goto(s+row*s,s+column*s)
def square(s,row,column):
t=turtle
t.penup()
n=0
for count in range(4):
t.pendown()
t.forward(s)
t.left(90)
t.end_fill()
t.penup()
main()
So today I was given an assignment that asked me to create a 5 by 5 checkerboard. So far, I have this code which manages to create most of the checkerboard. However, I still have a mistake somewhere or I am missing some key information.
The attached picture shows what the program looks like with the error.
The program started by creating the black square, which can be seen on the bottom left corner. Then it worked up until the top right corner, where the empty space can be seen.
Please help.
Let's try stamping instead of drawing. This gains us speed while simplifying our logic. We stamp one large black square to represent the board, then stamp the white squares onto it:
from turtle import Turtle, Screen
SQUARES_PER_SIDE = 5
CURSOR_SIZE = 20
def main():
length = int(input("Enter the length of each square: "))
screen = Screen()
screen.bgcolor("lightblue")
turtle = Turtle('square', visible=False)
turtle.shapesize(SQUARES_PER_SIDE * length / CURSOR_SIZE)
turtle.speed('fastest')
turtle.stamp() # black background
turtle.shapesize(length / CURSOR_SIZE)
turtle.fillcolor("white")
turtle.penup()
edge = (1 - SQUARES_PER_SIDE) / 2 * length # center of left or bottom square
turtle.goto(edge, edge)
for row in range(SQUARES_PER_SIDE):
for column in range(SQUARES_PER_SIDE):
if (row + column) % 2 == 0:
turtle.stamp() # white square
turtle.forward(length)
turtle.goto(edge, edge + (row + 1) * length)
screen.exitonclick()
main()
OUTPUT
Moving t.goto(s+row*s,s+column*s) to beginning of inner for loop does the trick.
Basically we need to move turtle to starting position first and then start drawing.
I also cleaned up the code to put redundant lines inside square function.
Also, added t.penup() so that turtle doesn't show draw until it has reached starting position and start drawing.
import turtle
def main():
t=turtle
t.penup()
s=int(input("Enter the length of each square: "))
t.screensize(2000,2000,"lightblue")
for row in range(0,5):
for column in range(0,5):
t.goto(s+row*s,s+column*s)
if (row+column)%2==0:
square(s,row,column,"black")
else:
square(s,row,column,"white")
def square(s,row,column,color):
t=turtle
t.pendown()
t.fillcolor(color)
t.begin_fill()
t.penup()
n=0
for count in range(4):
t.pendown()
t.forward(s)
t.left(90)
t.end_fill()
t.penup()
main()
Anil_M beat me to it by a few minutes; but I wanted to offer some additional code clean-up, as you've got too many needless penups, pendowns and unnecessary parameter passing going on.
Try this:
import turtle
t = turtle.Turtle()
t.speed(0)
def main():
s=int(input("Enter the length of each square: "))
for row in range(5):
for column in range(5):
if (row+column)%2==0:
color = "black"
else:
color = "white"
t.penup()
t.goto(row*s,column*s)
t.pendown()
filled_square(s, color)
def filled_square(s, color):
t.fillcolor(color)
t.begin_fill()
for count in range(4):
t.forward(s)
t.left(90)
t.end_fill()
main()
I'm being really bugged by a task:
User inputs radius r and then turtle draws the circle then proceeds to draw another circle with the same center but 10 px smaller until the radius is 0
First let us approximate a circle as a regular polygon with 36 sides/segments.
To draw this shape given a radius r we need to know;
The length of each segment
The angle to turn between each segment
To calculate the length, we first need the circumference, which is 2πr (we will approximate pi as 3.1415), giving us
circumference = 2 * 3.1415 * radius
Next we divide this by the number of segments we are approximating, giving
circumference = 2 * 3.1415 * radius
seg_lenght = circumferece/36
Now we need the angle difference between the segments, or the external angle. This is simply 360/n for a regular n-gon(polygon with n sides), so we do 360/36 = 10
We can now define a function to generate the segment length and draw the circle:
def circle_around_point(radius):
circumference = 2 * 3.1415 * radius
seg_length = circumference/36
penup()
fd(radius) #Move from the centre to the circumference
right(90) #Face ready to start drawing the circle
pendown()
for i in range(36): #Draw each segment
fd(seg_length)
right(10)
penup()
right(90) #Face towards the centre of the circle
fd(radius) #Go back to the centre of the circle
right(180) #Restore original rotation
pendown()
Now for the concentric circles:
def concentric_circles(radius):
while radius > 0:
circle_around_point(radius)
radius -= 10
It's not clear why #IbraheemRodrigues felt the need to recode turtle's circle() function based on your problem description, but we can simplify his solution by not reinventing the wheel:
def circle_around_point(turtle, radius):
is_down = turtle.isdown()
if is_down:
turtle.penup()
turtle.forward(radius) # move from the center to the circumference
turtle.left(90) # face ready to start drawing the circle
turtle.pendown()
turtle.circle(radius)
turtle.penup()
turtle.right(90) # face awary from the center of the circle
turtle.backward(radius) # go back to the center of the circle
if is_down:
turtle.pendown() # restore original pen state
def concentric_circles(turtle, radius):
for r in range(radius, 0, -10):
circle_around_point(turtle, r)
The key to circle() is that the current position is on the edge of the circle so you need to shift your position by the radius to make a specific point the center of the circle.
However, to solve this problem, I might switch from drawing to stamping and do it this way to speed it up and simplify the code:
import turtle
STAMP_SIZE = 20
radius = int(input("Please input a radius: "))
turtle.shape('circle')
turtle.fillcolor('white')
for r in range(radius, 0, -10):
turtle.shapesize(r * 2 / STAMP_SIZE)
turtle.stamp()
turtle.mainloop()
However, this draws crude circles as it's blowing up a small one:
To fix that, I might compromise between the two solutions above and do:
import turtle
radius = int(input("Please input a radius: "))
turtle.penup()
turtle.forward(radius)
turtle.left(90)
turtle.pendown()
turtle.begin_poly()
turtle.circle(radius)
turtle.penup()
turtle.end_poly()
turtle.addshape('round', turtle.get_poly()) # 'circle' is already taken
turtle.right(90)
turtle.backward(radius)
turtle.shape('round')
turtle.fillcolor('white')
for r in range(radius - 10, 0, -10):
turtle.shapesize(r / radius)
turtle.stamp()
turtle.mainloop()
This improves circle quality by shrinking a large one instead of enlarging a small one:
Where quality of the circle can be controlled using the steps= argument to the call to circle().
But, if I really wanted to minimize code while keeping quality high and speed fast, I might do:
import turtle
radius = int(input("Please input a radius: "))
for diameter in range(radius * 2, 0, -20):
turtle.dot(diameter, 'black')
turtle.dot(diameter - 2, 'white')
turtle.hideturtle()
turtle.mainloop()
The dot() method draws from the center instead of the edge, uses diameters instead of radii, draws only filled circles, and seems our best solution to this particular exercise:
import turtle
#### ##### #### Below class draws concentric circles.
class Circle:
def __init__(self, pen, cx, cy, radius):
self.pen = pen
self.cx = cx
self.cy = cy
self.radius = radius
def drawCircle(self):
self.pen.up()
self.pen.setposition( self.cx, self.cy - self.radius )
self.pen.down()
self.pen.circle(self.radius)
def drawConCircle(self, minRadius = 10, delta = 10):
if( self.radius > minRadius ) :
self.drawCircle()
self.radius -= delta # reduce radius of next circle
self.drawConCircle()
#### End class circle #######
win = turtle.Screen()
win.bgcolor("white")
s = Circle( turtle.Turtle(), 0, 0, 200 )
s.drawConCircle()
win.exitonclick()
How can I draw a rectangle where: the smallest is 5 in height and each consecutive rectangle adds the first rectangles height, i.e. 5, 10, 15, …. The width of each rectangle is 200. The color of the lines are blue and the fill color, from top to bottom is grey0, grey14, grey28, ….
How can I do this and make sure the picture fits onto the screen?
(Each new rectangle goes below the previous one)
This is what I have so far, but I don't know how I can fill it:
import turtle
def rectangle(t, l, w):
for i in range(2):
t.right(90)
t.forward(l)
t.right(90)
t.forward(w)
me = turtle.Turtle()
me.color('blue')
me.pensize(2)
me.penup()
l = 2.5
w = 250
x = 50
y = 150
for i in range(9):
rectangle(me, l, w)
l = l*2
w = w
x = x
y = y
me.setposition(x,y)
me.pendown()
def filled_rectangle(t, l, w):
t.begin_fill()
for i in range(2):
t.right(90)
t.forward(l)
t.right(90)
t.forward(w)
t.end_fill()
Filling the rectangles is simple as #JoranBeasley has addressed. However, your specification of "smallest is 5" and "make sure the picture fits onto the screen" are in conflict. We need to fit the rectangles to the screen and take whatever starting size we get. Since each rectangle is twice the height of the next, then the starting rectangle is the available height divided by 2 (since we're doubling) raised to the power of the number of grey shades you want to represent:
from turtle import Turtle, Screen
def rectangle(t, l, w):
t.begin_fill()
for _ in range(2):
t.right(90)
t.forward(l)
t.right(90)
t.forward(w)
t.end_fill()
screen = Screen()
me = Turtle(visible=False)
me.penup()
GREYS = [ # adjust to taste
('grey0' , '#000000'),
('grey14', '#242424'),
('grey28', '#474747'),
('grey42', '#6B6B6B'),
('grey56', '#8F8F8F'),
('grey70', '#B3B3B3'),
('grey84', '#D6D6D6'),
('grey98', '#FAFAFA'),
]
WIDTH = 2 ** (len(GREYS) + 1) # depends on font and keep below screen.window_width()
x = WIDTH / 2 # rectangle() draws right to left -- move x right to center drawing
canvas_height = screen.window_height() * 0.90 # use most of the space available
length = canvas_height / 2 ** len(GREYS) # determine starting length to fill canvas
y = canvas_height / 2 # begin at the top of canvas
fontsize = 1
for name, color in GREYS:
me.fillcolor(color)
me.setposition(x, y)
me.pendown()
rectangle(me, length, WIDTH)
me.penup()
if 4 <= fontsize <= length:
font = ("Arial", fontsize, "bold")
me.setposition(0, y - length / 2 - fontsize / 2)
me.write(name, align="center", font=font)
fontsize *= 2
y -= length
length *= 2
screen.exitonclick()
The width is more arbitrary than the height but I made it a function of the fontsize and the doubling so I could write the shade names in the rectangles:
I reverted the outline color to black instead of blue so there'd be pure black nearby to compare the grey shades against.
I need help capping off my for loops. (They can go on forever, yet I need them to be in range of 12 and 10.) My thinking is instead of this
for i in range(sides):
to do:
for sides in range(12):
#and for repeat do
for repeat in range(10):
This, in theory, should stop the possibly infinite process of looping, right? The second problem is my end_fill() doesn't fill in each shape with a different color. The outline and inside should be the same, and on a new shape, should be a random color (using randint function).
from turtle import *
import math
import random
#Continue being lazy and not creating turtles, also using a .cfg file to make the window.
colormode(255)
sides = int(input("Enter a number of sides (1-12): "))
repeat = int(input("How many times to repeat? (1-10): "))
#Turtle stuff.
penup()
goto(0,0)
size = 100
angle1 = 360 / sides
angle2 = 360 / repeat
#Here is where I am having issues, I am not sure how much to turn the turtle by do to the needed input
#Also I need to cap this off to only 12 sides and 10 repeats
#As it stands it can go for infinitum.
begin_fill()
for count in range(repeat):
for i in range(sides):
pendown() #Puts the pen down.
pensize(5) #Sets the pen to something more visible
colors1 = random.randint(0, 255) #Random red
colors2 = random.randint(0, 255) #Random blue
colors3 = random.randint(0, 255) #Random green
forward(size) #Goes forward 10 pixels
left(angle1)
penup()
#Goes left 360 / sides degrees. So 360 / 10 = 36 degrees.
pencolor(colors1, colors2, colors3) #Sets pencolor to a random RGB code
fillcolor(colors1, colors2, colors3) #Sets fillcolor to a random RGB code.
left(angle2) #Move left 90 degrees afterwards.
forward(5) #Moves forward 5 times.
end_fill() #Fills in the shape.
Code also available here: https://gist.github.com/anonymous/3984f7a1a04e9957ea55
Your first problem can be solved using Python 3 turtle's graphic numinput() instead of console input():
numinput(title, prompt, default=None, minval=None, maxval=None)
This will limit the range of the user's input. Your second issue is due to having begin_fill and end_fill at two different indentation levels. Usually, they should be at the same level. Here's a rework of your code with the above changes:
from turtle import Screen, Turtle
import random
screen = Screen()
screen.colormode(255)
sides = screen.numinput("Color Polygons", "Enter a number of sides (1-12)", default=6, minval=1, maxval=12)
if sides is None: # user cancelled operation
sides = 6
repeat = screen.numinput("Color Polygons", "How many times to repeat? (1-10)", default=5, minval=1, maxval=10)
if repeat is None:
repeat = 5
turtle = Turtle()
turtle.speed('fastest')
turtle.pensize(5)
turtle.penup()
size = 100
angle1 = 360 / sides
angle2 = 360 / repeat
for count in range(int(repeat)):
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
turtle.color(red, green, blue)
turtle.begin_fill()
for i in range(int(sides)):
turtle.pendown()
turtle.forward(size)
turtle.left(angle1)
turtle.penup()
turtle.end_fill()
turtle.left(angle2)
turtle.forward(5)
turtle.hideturtle()
screen.exitonclick()
I want to create concentric circles. I want the user to input how many circles they would like and at any specified radius. My problem is that the circles are not forming within one another.Any hints would be awesome
import turtle
import random
n1 = int(input("How many circles"))
n2 = int(input("Radius?"))
for i in range(n1):
turtle.penup()
turtle.right(50)
turtle.forward(i)
turtle.begin_fill()
turtle.color(random.random(), random.random(), random.random())
turtle.circle(n2)
turtle.end_fill()
turtle.pendown()
turtle.home()
while i in range(n1):
turtle.pendown()
turtle.right(40)
turtle.forward(i)
turtle.begin_fill()
turtle.color(random.random(), random.random(), random.random())
turtle.circle(n2-20)
turtle.end_fill()
turtle.penup()
import turtle
import random
num = int(input("How many circles? "))
radius = int(input("Radius? "))
# move to starting point - tangent to right edge of largest circle
turtle.forward(radius)
turtle.left(90)
# draw circles, largest to smallest
for circle in range(num, 0, -1): # (num .. 1)
# draw a filled circle
turtle.begin_fill()
turtle.color(random.random(), random.random(), random.random())
turtle.circle(radius * circle / num)
turtle.end_fill()
# shift inward to next circle starting-point
turtle.left(90)
turtle.forward(radius / num)
turtle.right(90)
given 6, 120 produces