Teknőcgrafika

Kategória: Python.

Áttekintés

A teknőcgrafika elsősorban oktatási céllal készült: ideális első találkozás gyerekek számára a programozással. Az alapötlet az, hogy egyszerű utasításokkal ("menj előre", "fordulj balra" stb.) mozgatunk egy teknőcöt, ami közben megrajzolja a bejárt útvonalat. Története 1967-ig, a Logo programozási nyelv megjelenéséig nyúlik vissza. A legismertebb Logo megvalósítás a Comenius Logo, amit a pozsonyi Comenius egyetemen fejlesztette ki. Pythonban a belső turtle könyvtár tartalmazza a megfelelő utasításokat.

Az alábbi oldalak segítettek ennek a leírásnak az elkészítésében:

Lehetőségek

Első program

A teknőcgrafikát Pythonban többféleképpen használhatjuk. Más leírások esetleg más módszert alkalmaznak; én a következőképpen szoktam használni:

from turtle import *
 
forward(100)
 
done()

Az eredmény:

nyil.png

A kód magyarázata:

  • from turtle import *: ezzel töltjük be a teknőcgrafika függvényeit. Természetesen az import turtle is működne, és alapvetően ez utóbbi megközelítést tartom szerencsésebbnek, viszont mivel itt elsősorban oktatási célról beszélünk, ahol nem használunk más könyvtárakat, a kód tömörebbé tétele érdekében hasznosabbnak tartom a fenti kódban megadott megoldást.
  • forward(100): a teknőc (ami jelen esetben egy nyíl hegye) előre megy 100 képpontnyit, miközben vonalat húz maga után. A teknőcnek van pozíciója és iránya. A kezdeti pozíció a (0, 0) koordináta, ami az ablak közepén van. A koordináta jobbra és felfelé nő. A méret nem egyértelmű, többfélével találkoztam és többfélét is tapasztaltam; általában pár százas nagyságrendű. A kezdeti irány jobbra mutat. Ha futtatjuk, akkor látható a mozgás is, nemcsak a végeredmény.
  • done(): Bizonyos rendszerekből indítva (pl. Visual Studio Code) az ablak egyből bezáródik; ez akadályozza meg a bezáródást. Más rendszerekben (pl. Mu) nem záródik be, így ott nincs szükség erre (de nem is ért, ha ott van).

A későbbiekben az import és a done() sorokat nem adjuk meg, csak a lényegi kódot.

Egyszerű alakzatok

Valósítsuk meg az alábbi programot:

forward(100)
right(90)
forward(100)
right(90)
forward(100)
right(90)
forward(100)
right(90)

Az eredmény:

negyzet.png

Ebben a programban előre megyünk 100 képpontnyit, utána jobbra fordulunk 90 fokot (right(90)), majd ismét előre megyünk és ismét fordulunk, összesen négyszer végrehajtva a műveletet. Mivel Pythonban vagyunk, használhatjuk erre a for ciklust:

for i in range(4):
    forward(100)
    right(90)

Ha még van olyan, aki idáig nem látta a rendszerben rejlő hatalmas oktatási potenciált, az szerintem legkésőbb ezen a ponton meglátja.

Minimális változtatással tudunk további eredményeket elérni:

for i in range(6):
    forward(70)
    right(60)

Eredmény:

hatszog.png

Sőt, általánosíthatjuk is, bevezetve ezzel a függvények fogalmát:

def n_szog(n):
    for i in range(n):
        forward(360 / n)
        right(360 / n)
 
n_szog(8)

Nyolcszöget kirajzolva az eredmény:

nszog.png

Minimális módosítással betiltott önkényuralmi jelképekhez hasonló ábrákat is készíthetünk:

for i in range(5):
    forward(100)
    right(144)
csillag.png

A spirál rajzolásakor a változók fogalmával is megismerkedhetünk:

méret = 5
for _ in range(28):
    forward(méret)
    left(90)
    méret += 5
spiral.png

Rajzolásnál fel is tudjuk emelni a "tollat"; ekkor mozgás közben nem rajzol:

for i in range(4):
    down()
    forward(20)
    up()
    forward(20)
szaggatott.png

Talán ebből már jól láthatóak a teknőcgrafika lehetőségei: egyrészt látványos ábrák készítése pár sorból, másrészt a programozási fogalmak bevezetése.

Kör

Kört a circle() függvénnyel tudunk rajzolni:

circle(50)

Ez egy 50 képpontnyi sugarú kört rajzol az aktuális pontból kiindulva, az aktuális irányban, az óramutató járásával ellenkező irányban.

kor.png

Ha a sugár negatív, akkor óramutató járásával megegyező irányban halad. Második, opcionális paraméterként megadhatunk egy fokokban kifejezett szöget, melynek alapértelmezett értéke 360, azaz egy teljes kör. Háromnegyed környi körívet az alábbi módon rajzolhatunk:

circle(-50, 270)                                                                                                                       }
koriv.png

Kitöltött kört, azaz nagy méretű pontot rajzolhatunk a dot() függvény segítségével:

dot(50)

A módszer nem konzekvens, ugyanis a kiindulás a kitöltött kör középpontja, paraméterként pedig az átmérőt kell megadni, nem a sugarat.

pont.png

Paraméterek

A fenti példákban egy fekete nyíl mozgott, amely egy képpont vastagságnyi fekete vonalat húzott. További lehetőségek:

title('Négyzet')
shape('turtle')
pensize(5)
pencolor('red')
speed(5)
 
for i in range(4):
    forward(100)
    right(90)
parameter.png

Magyarázat:

  • title('Négyzet'): az ablak címét változtatja meg az alapértelmezettről.
  • shape('turtle'): a teknőc alakját változtatja meg valóban teknőcre.
  • pensize(5): a vonal vastagsága 5 képpont 1 helyett.
  • pencolor('red'): a vonal színe piros lesz.
  • speed(5): a teknőc sebességét lehet ezzel beállítani; minél nagyobb a szám, annál gyorsabb. A maximális sebességet még a 0 paraméterrel is beállíthatjuk.

Kitöltés

Alakzatokat kitölteni a begin_fill() és end_fill() hívásokkal lehet. A fillcolor(…) hívással adhatjuk meg a kitöltés színét. Példa:

pensize(5)
pencolor('blue')
fillcolor('orange')
begin_fill()
for i in range(4):
    forward(100)
    right(90)
end_fill()
kitoltott.png

Az end_fill() hatására a teknőc ugyanabba a pozícióba ugrik, ahol volt a begin_fill() híváskor. Célszerű úgy megvalósítani a mozgást, hogy eleve ott fejezze be.

Koordináták

A goto(x, y) hatására a megadott koordinátára ugrik a teknőc. Ha a toll le van helyezve, akkor ebben az esetben is rajzol.

Az alábbi példában 4 koordinátára ugrik, és ott "pecsétel" egyet-egyet a stamp() hívás segítségével:

shape('turtle')
shapesize(5, 5, 5)
up()
 
goto(100, 100)
stamp()
 
goto(100, -100)
stamp()
 
goto(-100, -100)
stamp()
 
goto(-100, 100)
stamp()
koordinata.png

A shapesize() hívással magának a teknőcnek a méreteit lehet átállítani (szélesség, magasság, körvonal).

Példák

Az alábbiakban néhány pár soros példát láthatunk, ami látványos eredményt ad.

Nap

fillcolor('orange')
begin_fill()
for i in range(36):
    forward(200)
    left(170)
end_fill()
nap.png

Rozetta

for i in range(10):
    for j in range(10):
        forward(20)
        left(36)
    left(36)
rozetta.png

Körök

for i in range(36):
    right(10)
    circle(50)
korok.png

Sakktábla

hideturtle()
begin_fill()
for i in range(34):
    forward(160 if i % 2 == (0 if i <= 16 else 1) else 20)
    left(90 if (i + (0 if i < 16 else 1 if i > 16 else 2)) // 2 % 2 == 0 else -90)
end_fill()
sakktabla.png

Ez a kód talán kevésbé érthető. Én készítettem úgy, hogy először szinte egyesével rajzolta ki a vonalakat, majd egyszerűsítettem le egyetlen ciklussá.

Benzol

színek = ['red', 'purple', 'blue', 'green', 'orange', 'yellow']
bgcolor('black')
for i in range(360):
    pencolor(színek[i % 6])
    width(i // 100 + 1)
    forward(i)
    left(59)
benzol.png
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License