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()
Related
We were assigned to make a pizza using user-inputted amount of slices, but I can't figure out how to tilt the slice.
import turtle
window = turtle.Screen()
window.bgcolor("lightgreen")
slice = turtle.Turtle()
slice.color("orange")
slice_amount = int(input("How many slices do you want to make? "))
if slice_amount == slice_amount:
slice.tilt(360/slice_amount)
def pizza(angle, radius, t):
t.begin_fill()
t.setheading((180 - angle) / 2)
t.forward(radius)
t.setheading(-0.5 * angle + 180)
t.circle(radius, angle)
t.goto(0, 0)
t.end_fill()
for i in range(slice_amount -1):
t.begin_fill()
t.setheading((180 - angle) / 2)
t.forward(radius)
t.setheading(-0.5 * angle + 180)
t.circle(radius, angle)
t.goto(0, 0)
t.end_fill()
pizza(360/slice_amount, 100, slice)
turtle.done()
I tried to put the whole function in an if statement but that didn't help.
When you're drawing shapes around a circle, the typical approach is to:
draw a shape
move back to the origin
point the turtle in the direction of the next shape
go back to step 1
You're missing step 3, positioning the turtle so it's ready to draw the next thing. Without this step, it winds up repeatedly drawing the same shape over and over.
One approach is to set the heading to point at the origin before goto(0, 0), then rotate 180 degrees to point directly at the line the turtle has just drawn to close the last pie slice.
import turtle
n = 6
radius = 100
angle = 360 / n
t = turtle.Turtle()
for i in range(n):
t.color(i / n, 0, 0)
t.begin_fill()
t.forward(radius)
t.left(90)
t.circle(radius, angle)
t.setheading(t.towards(0, 0))
t.goto(0, 0)
t.left(180)
t.end_fill()
turtle.exitonclick()
Another option is to use your i to set the heading for each slice:
# ...
for i in range(n):
t.setheading(i * angle)
t.color(i / n, 0, 0)
t.begin_fill()
t.forward(radius)
t.left(90)
t.circle(radius, angle)
t.goto(0, 0)
t.end_fill()
# ...
When you're working on getting your logic correct, try to avoid functions and input(). Adding those things too soon adds complexity that gets in the way of your logic and slows down experimentation. Once you've ensured correctness, then you can split logic into functions and add extra features like user interaction.
Additionally, slice() is a builtin function in Python, so pick a different name for your variable to avoid overwriting it.
if slice_amount == slice_amount: does nothing so you can remove that.
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:
How to make the center point the center of my square? Right now it becomes the corner:
def draw_square(t, center_x, center_y, side_length):
"""
Function draw_square draws a square
Parameters:
t = reference to turtle
center_x = x coordinate of the center of square
center_y = y coordinate of the center of square
side_length = the length of each side
Returns:
Nothing
"""
t.up() #picks up tail of turtle
t.goto(center_x, center_y) #tells turtle to go to center of command
t.down() #puts tail down
for sides in range(4): #creates loop to repeat 4 times
t.left(90) #turns left 90 degrees
t.forward(side_length) #move forward the length given
def main(): #defines main function
import turtle #imports turtle module
t = turtle.Turtle() #attaches turtle to t
draw_square(t, 100, 100, 75) #uses the value to make square
main() #calls function
The solution is simple geometry, no sines nor secants involved. Simply calculate half of your side_length then add it to the X coordinate, and subtract it from your Y coordinate:
from turtle import Screen, Turtle # import turtle module
def draw_square(t, center_x, center_y, side_length):
"""
Function draw_square draws a square
Parameters:
t = reference to turtle
center_x = x coordinate of the center of square
center_y = y coordinate of the center of square
side_length = the length of each side
Returns:
None
"""
offset = side_length/2
t.penup() # picks up pen of turtle
t.goto(center_x, center_y) # tell turtle to go to center of drawing
t.dot() # visualize center of square (for debugging)
t.goto(center_x + offset, center_y - offset) # adjust for drawing from corner
t.pendown() # put pen down
for _ in range(4): # create loop to repeat 4 times
t.left(90) # turn left 90 degrees
t.forward(side_length) # move forward the length given
def main(): # define main function
t = Turtle() # attach turtle to t
draw_square(t, 100, 100, 75) # use the values to make a square
screen = Screen()
main() # call function
screen.exitonclick()
I'm trying to draw a checkerboard.
I drew the board, but now I have to define a function (a loop) that fills in every other square with black. I've been trying to write a loop to do this for a while, can someone help?
Here's my code:
import turtle
def drawGrid():
turtle.penup()
turtle.goto(-300, 250)
turtle.pendown()
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
def drawColumns():
for i in range(4):
turtle.right(90)
turtle.forward(37.5)
turtle.right(90)
turtle.forward(300)
turtle.left(90)
turtle.forward(37.5)
turtle.left(90)
turtle.forward(300)
def drawRows():
turtle.left(180)
rows = 0
while rows <= 3:
rows += 1
turtle.forward(37.5)
turtle.right(90)
turtle.forward(300)
turtle.left(90)
turtle.forward(37.5)
turtle.left(90)
turtle.forward(300)
turtle.right(90)
def main():
drawGrid()
drawColumns()
drawRows()
if __name__ == "__main__":
main()
Turtles fill method works on shapes, i.e. a completely bounded area. So rather than drawing a grid you need to think in terms of drawing a series of squares.
So lets start by defining a simple function to draw a filled in square. It takes a turtle object and a size which is the length of the side.
import turtle
def draw_filled_square(this_turtle, size):
"""Draw a square by drawing a line and turning through 90 degrees 4 times"""
this_turtle.pendown()
this_turtle.fill(True)
for _ in range(4):
this_turtle.forward(size)
this_turtle.right(90)
this_turtle.fill(False)
this_turtle.penup()
we can call it like this:
window = turtle.Screen()
myturtle = turtle.Turtle()
square_size = 90
myturtle.goto(-300, 200)
draw__filled_square(myturtle, square_size)
Which draws a single square. Note that it puts it back at the starting place, so we need to move it before drawing the next square.
Now, in practice, as long as we draw the outline of the box we only need to draw filled squares, unfilled squares can be represented negative space. But for the purposes of explanation I'm going to also draw them.
Defining a function for an unfilled square is easy -- just duplicate the existing function but set this_turtle.fill(False) at the beginning instead.
Anytime something needs to count in a repeating sequence (1, 2, 3, 4, 1, 2, 3, 4, ...) it calls for use of modulo (remainder). Modulo means remainder so if x modulo y is 0 it means x is exactly divisible by y. This translates into code as if x % y == 0:
Here's a simple drum machine to demonstrate:
def drum_loop(x):
# go bang on the fourth beat
if x % 4 == 0:
print("bang!")
else:
print("tish")
# prints tish, tish, tish, bang! tish, tish, tish, bang!
for i in range(1,9):
drum_loop(i)
Alternating is just like counting 0, 1 , 0, 1 repeatedly.
So we can draw a row like this:
for i in range(8):
if i % 2 == 0:
draw_filled_square(myturtle, square_size)
else:
draw_unfilled_square(myturtle, square_size)
# move to start of next square
myturtle.forward(square_size)
Now just repeating this isn't going to do the trick, but it should be clear you can use modulo 2 again to make the rows alternate properly.
Do this by defining a row function that will alternate between starting with a black and starting with a white square, then calling this from within another loop. (Don't forget to go back to the beginning and move down every time you start a row).
Here's another example where drawing creates more work for the poor turtle than simply stamping. Rather than thinking about drawing and filling boxes, think about the board itself as a filled square onto which other filled squares are stamped:
from turtle import Turtle, Screen
NUMBER_SQUARES = 8
SQUARE_SIZE = 40
BOARD_SIZE = SQUARE_SIZE * NUMBER_SQUARES
BORDER_FRACTION = 1.025 # add a slight edge to board
STAMP_SIZE = 20 # size of turtle square image
turtle = Turtle(shape='square', visible=False)
turtle.shapesize(BOARD_SIZE / STAMP_SIZE * BORDER_FRACTION)
turtle.color('black')
turtle.stamp()
turtle.shapesize(SQUARE_SIZE / STAMP_SIZE)
turtle.color('white')
turtle.penup()
for y in range(-NUMBER_SQUARES//2, NUMBER_SQUARES//2):
parity = y % 2 == 0
for x in range(-NUMBER_SQUARES//2, NUMBER_SQUARES//2):
if parity:
turtle.goto(x * SQUARE_SIZE + SQUARE_SIZE//2, y * SQUARE_SIZE + SQUARE_SIZE//2)
turtle.stamp()
parity = not parity
Screen().exitonclick()
This solution can print a board in any two colors (e.g. black and red), it doesn't assume a white background. Just another example of better living through stamping.
import turtle
turtle.pensize(2)
turtle.penup()
turtle.goto(-160,-160)
turtle.pendown()
turtle.color("black")
for i in range(4):
turtle.forward(320)
turtle.left(90)
for y in range(-160,160,80):
for x in range(-160,160,80):
turtle.begin_fill()
turtle.penup()
turtle.goto(x,y)
turtle.pendown()
for k in range(4):
turtle.forward(40)
turtle.left(90)
turtle.end_fill()
for y in range(-120,160,80):
for x in range(-120,160,80):
turtle.begin_fill()
turtle.penup()
turtle.goto(x,y)
turtle.pendown()
for k in range(4):
turtle.forward(40)
turtle.left(90)
turtle.end_fill()
turtle.done()
Let's have a look at the zig-zag approach (the explanation of the code is commented inside):
import turtle
def drawGrid(rows, cols, size):
turtle.sety(turtle.ycor() + size * rows) # Draw the initial line
f = size * 2
turtle.begin_fill()
for j in range(cols): # Make the columns
if j % 2:
turtle.backward(f) # Make room for the zig-zag up and zig-zag down
for i in range(rows * 2): # rows * 2 because there will be both zig-zag down and a zig-zag up for each row
turtle.forward(size)
turtle.right(90)
if i % 2:
turtle.left, turtle.right = turtle.right, turtle.left # Switch the zig-zag direction
turtle.left(180)
turtle.end_fill()
turtle.sety(turtle.ycor() - size * rows) # Draw the final line
turtle.penup()
turtle.goto(-300, -50) # Set the bottom-left position of the grid
turtle.pendown()
turtle.speed("fastest") # Because I have no patience
drawGrid(8, 8, 40)
Output:
Note that the number of rows and columns must be even for this to work.
I need to draw a square given a center point using the turtle module.
def drawCentSq(t,center,side):
xPt=center[0]
yPt=center[1]
xPt-=int(side/side)
yPt+=int(side/side)
t.up()
t.goto(xPt,yPt)
t.down()
for i in range(4):
t.forward(side)
t.right(90)
def main():
import turtle
mad=turtle.Turtle()
wn=mad.getscreen()
print(drawCentSq(mad,(0,0),50))
main()
I'm having a hard time making my turtle go to the right starting point.
You need:
xPt-=int(side/2.0)
yPt+=int(side/2.0)
As it was you were just += and -= 1.
I need to draw a square given a center point using the turtle module.
As #seth notes, you can do this by fixing the center calculation in your code:
from turtle import Turtle, Screen
def drawCentSq(turtle, center, side):
""" A square is a series of perpendicular sides """
xPt, yPt = center
xPt -= side / 2
yPt += side / 2
turtle.up()
turtle.goto(xPt, yPt)
turtle.down()
for _ in range(4):
turtle.forward(side)
turtle.right(90)
yertle = Turtle()
drawCentSq(yertle, (0, 0), 50)
screen = Screen()
screen.exitonclick()
But let's step back and consider how else we can draw a square at a given point of a given size. Here's a completely different solution:
def drawCentSq(turtle, center, side):
""" A square is a circle drawn at a rough approximation """
xPt, yPt = center
xPt -= side / 2
yPt -= side / 2
turtle.up()
turtle.goto(xPt, yPt)
turtle.right(45)
turtle.down()
turtle.circle(2**0.5 * side / 2, steps=4)
turtle.left(45) # return cursor to original orientation
And here's yet another:
STAMP_UNIT = 20
def drawCentSq(turtle, center, side):
""" A square can be stamped directly from a square cursor """
mock = turtle.clone() # clone turtle to avoid cleaning up changes
mock.hideturtle()
mock.shape("square")
mock.fillcolor("white")
mock.shapesize(side / STAMP_UNIT)
mock.up()
mock.goto(center)
return mock.stamp()
Note that this solution returns a stamp ID that you can pass to yertle's clearstamp() method to remove the square from the screen if/when you wish.