3

I am experiencing trouble with my code it is supposed to be drawing a house with a cross through the center but is getting messed up somewhere and I cant figure out where.

import turtle
def drawhouse(bob):
    pairs = [(100, 135), (70.71, -135), (100, -90), (50, 0), (50, 90), (50, 180), (50, 90), (50, 0), (100, 90), (70.71, -45), (100, -90)]
    for pair in pairs:
        bob.forward(pair[0])
        bob.left(pair[1])  
def main():
    screen = turtle.Screen()
    screen.bgcolor("white")
    screen.title("Turtle House")
    bob = turtle.Turtle()
    bob.color("black")
    bob.speed(0)
    drawhouse(bob)
    turtle.done()

if __name__ == "__main__":
    main()  

The image it is supposed to look like:

the image it is suppose to look like

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • You go forward 100, then turn 135 degrees to the left. Go forward ~70, and then turn 135 degrees to the right. So now you're at the top of the house, but instead of pointing to the left and down, you're pointing straight to the right again. Why did you expect this to work? How did you arrive at the list of distances and angles? Also, if you've ever done this puzzle by hand, you probably found that it's easier to start in a corner that has 3 lines coming in. (or perhaps that's what you were going for, and the ~70 distance is a miscalculation, but the problem is with the 2nd step either way) – Grismar Apr 23 '23 at 22:26
  • While It's relatively easy to fix it for you, let me rather suggest you a debug approach. As it is clear your `pairs` are incorrct at some point you need to find where. So reformat your code to have each pair in separate line. Comment then all out, and then uncomment one and run. Then another and run and so on, fixing icorrect steps as you go. that should be miuch easier to deal with – Marcin Orlowski Apr 23 '23 at 22:27

3 Answers3

1

There are a few strategies you can take, but I wouldn't hardcode the points, especially if you're just getting them by trial and error. That sort of works for one shape, but it also forfeits the opportunity to understand and encode the nature of the shapes you're drawing. We should be able to draw in a way that makes it easy to scale, rotate and generalize the shape to create different patterns.

As with any problem, find a simpler problem and start formulating a strategy. Can you draw a single triangle? If not, perhaps start with a square. These are sub-components of the larger drawing, so if you can figure out how to draw these, you can probably figure out the next step of putting them together to complete the pattern.

Drawing a 45-45-90 degree triangle is a bit tricky, but you can look up the formula:

import turtle


length = 100
side_length = 2 ** 0.5 * length

t = turtle.Turtle()
t.forward(length)
t.left(135)
t.forward(side_length)
t.left(135)
t.forward(length)

turtle.exitonclick()

That's one sub-step. Another shape that might be handy is the "hat", which we can derive from the above shape by experimenting and observing that the side (hypotenuse) length is half of what it is in the 45-45-90 triangle.

length = 100
side_length = 2 ** 0.5 * length  # same as above

t = turtle.Turtle()
t.left(45)
t.forward(side_length / 2)
t.left(90)
t.forward(side_length / 2)
t.left(135)
t.forward(length)

With this shape, we can build the final result. The usual way to repeat things in programming is with loops. If we use a plain for _ in range(3):, we can repeat the drawing 3 times, but it'll just write over itself again and agin.

To achieve the desired result, we'll need to add some code to position the turtle so that it's primed to draw the next shape when it finishes the current loop.

# same initialization as above ...

for _ in range(3):
    t.left(45)
    t.forward(side_length / 2)
    t.left(90)
    t.forward(side_length / 2)
    t.left(135)
    t.forward(length)

    # prepare for the next triangle
    t.left(90)
    t.forward(length)
    t.left(90)

turtle.exitonclick()

This is not the most elegant approach as lines are drawn multiple times, but the point is that we've broken the problem down, come up with a general strategy based on simpler shapes and built up to a full solution. Unlike a points-based approach, all we need to do is change length to draw houses of different sizes, position the turtle at a different start point to translate the house, or start with a different turtle heading to draw houses at different angles.

I'll leave adding the hat and figuring out a strategy for drawing the house without overlapping as exercises. You can combine the hat with the full 45-45-90 triangle hypotenuse and a plain square to do so.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
1

Approaching this in terms of "turning angles" requires a bit more mental gymnastic than absolute angles. You could make it work with absolute angles first (using setheading()) and convert it to relative angles afterwards if needed.

A single line path for the house (without lifting the pen or double-backing on lines could be this:

LINE                        DIST. HEADING       ANGLE Delta 
Up by wall height           100      90°           +90
right by house width        100       0°           -90 
down-left on main diagonal  141.4  -135°          -135 
right by house width        100       0°          +135 
up by wall height           100      90°           +90
up-left on roof diagonal    71.1    135°           +45
down-left on roof diagonal  71.1   -135°          -270 (or +90)
down-right on main diagonal 141.4   -45°           +90

The resulting list of distance/angle pairs would be:

[(0,90), (100,-90), (100, -135), (141.4, 135), (100, 90), 
 (100,45), (71.1,90), (71.1,90),(141.4,0)]    

Note that this starts with a distance of zero because the angle needs to be set before the first move. If your loop changed the angle before moving forward, this extra pair would not be needed

Alain T.
  • 40,517
  • 4
  • 31
  • 51
0

I see this as a shape built with five of the same building block. So, let's make the turtle be that building block and stamp it five times:

from turtle import Screen, Turtle

def drawhouse(turtle):
    turtle.penup()

    for _ in range(4):
        turtle.stamp()
        turtle.left(90)

    turtle.setheading(90)
    turtle.forward(100)
    turtle.stamp()

screen = Screen()
screen.title("Turtle House")
screen.register_shape('isosceles', ((0, 0), (-50, -50), (50, -50)))

yertle = Turtle()
yertle.hideturtle()
yertle.shape('isosceles')
yertle.fillcolor(screen.bgcolor())

drawhouse(yertle)

screen.exitonclick()
cdlane
  • 40,441
  • 5
  • 32
  • 81