Naar www.aaappp.nl/informatica of Praktijkopdracht programmeren in Python

Huisjes tekenen met Python Turtle

Hieronder staat een beschrijving van de ontwikkeling van een Python-programma om met de turtle huisjes te tekenen. Het begint met een "quick and dirty"-versie voor het tekenen van twee huisjes. Daarna volgen we het proces van "refactoring" oftewel het verbeteren van de code zoals een professionele programmeur dat zou doen. Hierbij volgen we het DRY principe. DRY staat voor Don't Repeat Yourself. Het idee is dat je een stukje code een keer schrijft en daarom maar een keer goed hoeft te testen. Daarna kan je dit stukje code op allerlei plaatsen steeds opnieuw hergebruiken.

Versie 0: Quick and dirty met ruitjespapier

De programmeur heeft vooraf op ruitjespapier twee huisje getekend en toen de coördinaten in de commando's gezet.

import turtle
t = turtle.Turtle()

# teken een huisje
t.pendown()
t.goto(140,0)
t.goto(140,80) 
t.goto(70,120) 
t.goto(0,80)
t.goto(0,0)

# ga naar rechts en teken nog een huisje
t.penup()
t.goto(-150,0)
t.pendown()
t.goto(-10,0)
t.goto(-10,80) 
t.goto(-80,120) 
t.goto(-150,80)
t.goto(-150,0)

# klaar en maak de turtle onzichtbaar
t.hideturtle()
    

Versie 1: DRY code voor huisje

De twee huisjes zijn precies hetzelfde, maar ze staan op verschillende plekken en hebben dus verschillende coördinaten. Bij de eerste refactoring-stap laten we de computer de coördinaten uitrekenen. In dit geval verschillen alleen de X-coördinaten. In het algemene geval kunnen zowel X als Y verschillend zijn. Volgens het DRY-principe kunnen we die code vervangen in een volgende refactoring-stap.

import turtle
t = turtle.Turtle()

# teken een huisje
t.penup()
t.goto(0,0)
t.pendown()
t.goto(140,0)
t.goto(140,80) 
t.goto(70,120) 
t.goto(0,80)
t.goto(0,0)

# ga naar rechts en teken nog een huisje
t.penup()
t.goto(0-150,0)
t.pendown()
t.goto(140-150,0)
t.goto(140-150,80) 
t.goto(70-150,120) 
t.goto(0-150,80)
t.goto(0-150,0)

# klaar en maak de turtle onzichtbaar
t.hideturtle()
    

Versie 2: over functies, parameters en argumenten

Functies maak je dus met def en 0 of meer parameters tussen haakjes. Bij de aanroep van een functie geef je 0 of meer argumenten door. Zo'n argument is een waarde voor zo'n parameter.

In versie 2 heeft huisje 2 parameters: x en y. Bij de eerste aanroep van huisje(0,0) zijn de argumenten 0 en 0. De parameters krijgen dus deze waarden: x = 0 en y = 0.
Bij de tweede aanroep huisje(-150,0) wordt dat: x = -150 en y = 0 met als effect dat het tweede identieke huisje -150 naar links wordt getekend.

import turtle
t = turtle.Turtle()

def huisje(x, y):
    t.penup()
    t.goto(x,y)
    t.pendown()
    t.goto(140+x,  0+y)
    t.goto(140+x, 80+y)
    t.goto( 70+x,120+y)
    t.goto(  0+x, 80+y)
    t.goto(  0+x,  0+y)

# teken 2 huisjes    
huisje(0,0)
huisje(-150,0)

# teken een straat met huisjes
for straat in range(-360, 300, 60):
    print(straat)             
    huisje(straat,-160) 

# klaar en maak de turtle onzichtbaar
t.hideturtle()
    

In versie 2 is de aanroep van hideturtle commentaar, zodat je de turtle wel kunt zien.

Onderzoek in de Python-shell hoe je de onderstaande tekening ongeveer kunt namaken door middel van aanroepen van huisje met verschillende argumenten. Probeer dit uit!
De coördinaat (0,0) is de hoek linksonder van het rechter middelste huisje.
Onderzoek hoe hoog, laag, naar links en naar rechts je huisjes kunt tekenen. Maak eventueel het window groter.

Versie 3: huisjes in een for-loop is een straat

import turtle
t = turtle.Turtle()

def huisje(x, y):
    t.penup()
    t.goto(x,y)
    t.pendown()
    t.goto(140+x,  0+y)
    t.goto(140+x, 80+y)
    t.goto( 70+x,120+y)
    t.goto(  0+x, 80+y)
    t.goto(  0+x,  0+y)

# teken 2 huisjes    
huisje(0,0)
huisje(-150,0)

# teken een straat met huisjes
for straat in range(-360, 300, 60):
    print(straat)             
    huisje(straat,-160) 

# klaar en maak de turtle onzichtbaar
t.hideturtle()
    

In versie 3 tekent de turtle een hele straat met huisjes. Met range(start, stop, step) tel je vanaf start tot stop in step stappen. Omdat een debug-print is tussengevoegd, zie je in de Python-shell de verschillende waarden van de variabele straat.

Versie 3 is nog niet helemaal goed: de huisjes staan door elkaar. Zorg dat de huisjes los van elkaar komen te staan staan. Experimenteer met verschillende argumenten in de range van de for-loop.

Versie 4: ramen, deuren en kleuren

import turtle
t = turtle.Turtle()

def huisje(x, y):
    t.penup()
    t.goto(  0+x,  0+y)
    t.fillcolor('yellow')
    t.begin_fill()
    t.pendown()
    t.goto(140+x,  0+y)
    t.goto(140+x, 80+y)
    t.goto( 70+x,120+y)
    t.goto(  0+x, 80+y)
    t.goto(  0+x,  0+y)
    t.end_fill()


def deur(x, y):
    t.penup()
    t.goto(  0+x,  0+y)
    t.fillcolor('red')
    t.begin_fill()    
    t.pendown()
    t.goto(40+x, 0+y)
    t.goto(40+x,60+y)
    t.goto( 0+x,60+y)
    t.goto( 0+x, 0+y)
    t.end_fill()
        
def raam(x, y):
    t.penup()
    t.goto(  0+x,  0+y)
    t.fillcolor('blue')
    t.begin_fill()    
    t.pendown()
    t.goto(40+x, 0+y)
    t.goto(40+x,40+y)
    t.goto( 0+x,40+y)
    t.goto( 0+x, 0+y)
    t.end_fill()
        
# teken 2 huisjes met deuren en ramen    
huisje(0,0)
deur(80,0)
raam(20,20)
huisje(-150,0)
deur(-150+80,0)
raam(-150+20,0+20)

# klaar en maak de turtle onzichtbaar
t.hideturtle()
    

De programmeur heeft deuren, ramen en kleuren toegevoegd.
Het huisje, de ramen en deuren kan je op verschillende plekken neerzetten door bij de aanroep van functie huisje, deur of raam verschillende x,y-coördinaten door te geven.
De Python Turtle volgt de vorm die wordt getekend tussen begin_fill en end_fill. De kleur wordt achteraf in de tekening gegoten.

Versie 5: default parameter voor kleur

  
import turtle
t = turtle.Turtle()

def huisje(x, y, kleur='yellow'):
    t.penup()
    t.goto(  0+x,  0+y)
    t.fillcolor(kleur)
    t.begin_fill()
    t.pendown()
    t.goto(140+x,  0+y)
    t.goto(140+x, 80+y)
    t.goto( 70+x,120+y)
    t.goto(  0+x, 80+y)
    t.goto(  0+x,  0+y)
    t.end_fill()


def deur(x, y):
    t.penup()
    t.goto(  0+x,  0+y)
    t.fillcolor('red')
    t.begin_fill()    
    t.pendown()
    t.goto(40+x, 0+y)
    t.goto(40+x,60+y)
    t.goto( 0+x,60+y)
    t.goto( 0+x, 0+y)
    t.end_fill()
        
def raam(x, y):
    t.penup()
    t.goto(  0+x,  0+y)
    t.fillcolor('blue')
    t.begin_fill()    
    t.pendown()
    t.goto(40+x, 0+y)
    t.goto(40+x,40+y)
    t.goto( 0+x,40+y)
    t.goto( 0+x, 0+y)
    t.end_fill()
        
# teken 2 huisjes met deuren en ramen    
huisje(0,0)
deur(80,0)
raam(20,20)
huisje(-150,0)
deur(-150+80,0)
raam(-150+20,0+20)

# teken 1 huisje in een andere kleur en deur verwisseld met raam
huisje(150,0,'grey')
deur(150+20,0)
raam(150+80,20)

# klaar en maak de turtle onzichtbaar
t.hideturtle()
    

De programmeur wilde een huisje met een andere kleur, maar had geen zin om een extra functie te schrijven. En hij had ook geen zin om de aanroep voor de gewone huisjes te wijzigen. In de definitie van de functie huisje heeft hij daarom een default kleur gespecificeerd. Indien je bij de aanroep geen argument voor de kleur opgeeft, gebruikt huisje de default kleur. Indien je bij de aanroep een kleur opgeeft, gebruikt huisje die kleur.

Samenvatting

Op de eerste webpagina en de vorige webpagina had je al veel geleerd. Dit is alles wat je van deze webpagina moest leren.

Je bent nu klaar om de praktische opdracht te maken of je kunt je nog verdiepen in Perspectief voor beginners.