Autorské riešenie
[stiahni py, py]

  • Počet riešiteľov: 9 / 12 =  75 %

  • Úspešnosť riešenia: 4,67 / 5 = 93 %

Podľa zadania máme vykresliť hviezdicu so zadaným počtom ramien, zadanou dĺžkou ramien a zadanou farbou vnútornej plochy hviezdice.

Najprv poďme vyriešiť jednoduchšie úlohy. Pozrime sa ako by sme vykreslili kružnicu so zadaným polomerom a zadaným počtom bodov na nej (na obrázku nižšie).

Kružnica s polomerom 200 a 5 bodmi na jej obvode

Funkcia kresli_kruznicu_s_bodmi s dvomi parametrami pocet_bodov a polomer môže vyzerať napr. nasledovne:

def kresli_kruznicu_s_bodmi(pocet_bodov, polomer):
    for _ in range(pocet_bodov):
        pero.circle(polomer, 360 / pocet_bodov)
        pero.dot(7)

V programe sme použili funkciu circle s dvomi parametrami, ktorá vykresľuje ľavotočivý kruhový oblúk so zadaným polomerom a zadaným uhlom otočenia.

Teraz poďme nakresliť hviezdicu so zadaným polomerom a zadaným počtom bodov pozostávajúcu z rovnakých kružnicových oblúkov ako v predchádzajúcej úlohe (na obrázku nižšie).

Hviezdica s polomerom 200 a 5 bodmi

Na tomto obrázku je zrejmé, že prvý ľavotočivý vykreslený oblúk je rovnaký ako oblúk vykreslený na kružnici. Ostatné ľavotočivé oblúky budeme vykresľovať pravotočivo (v smere otáčania hodinových ručičiek). Po vykreslení každého kružnicového obblúku je potrebné sa otočiť vpravo o určitý uhol. Pre určenie tohto uhla nám pomôžu obrázok nižšie.

Hviezdica s polomerom 200 a 5 bodmi s pomocnými uhlami

Na konci každého oblúka je potrebné sa vzhľadom ku koncu  predchádzajúceho oblúka otočiť vpravo o uhol 360 / pocet_bodov. Po vykreslení každého ľavotočivého oblúka sa kurzor natočí vľavo o uhol 360 / pocet_bodov. Aby sa natočil do požadovaného pravotočívého smeru je potrebné ho otočiť vpravo o dvojnásobný uhol, t.j. 2 * 360 / pocet_bodov.

def kresli_hviezdicu_s_bodmi(pocet_bodov, polomer):
    for _ in range(pocet_bodov):
        pero.circle(polomer, 360 / pocet_bodov)
        pero.right(2 * 360 / pocet_bodov)
        pero.dot(7)

Aby sme vyriešili celé zadanie úlohy, je potrebné, aby sa po vykreslení obvodu vykreslili aj jednotlivé ramená. Na to je potrebné sa natočiť do stredu hviezdice, presunúť sa do stredu a odtiaľ vykresľovať jednotlivé ramená. Z obrázka zistíme, že patričný uhol otočenia je 90 - 360 / pocet_bodov.

Výsledný program na vykreslenie hviezdice so zadaným počtom a dĺžkou ramien a zadanou farbou výplne môže vyzerať napríklad nasledovne:

import turtle


def kresli_hviezdicu(pocet_ramien, dlzka_ramien, farba_vyplne):
    # obvod hviezdice
    pero.fillcolor(farba_vyplne)
    pero.begin_fill()
    for _ in range(pocet_ramien):
        pero.circle(-dlzka_ramien, 360 / pocet_ramien)
        pero.left(720 / pocet_ramien)
    pero.end_fill()
    # ramená hviezdice
    pero.left(90 - 360 / pocet_ramien)
    pero.forward(dlzka_ramien)
    pero.left(180)
    for _ in range(pocet_ramien):
        pero.forward(dlzka_ramien)
        pero.forward(-dlzka_ramien)
        pero.left(360 / pocet_ramien)


pero = turtle.Turtle()
tabula = turtle.Screen()
kresli_hviezdicu(5, 150, 'lightblue')
tabula.mainloop()			  

Iným alternatívnym riešením je vykresľovanie hviezdice po segmentoch. Na obrázku nižžie je vykreslená 5-ramenná hviezdica ABCDE so stredom S. Jej jednotlivé segmenty budeme vykresľovať v poradí SABS, SBCS, SCDS, SDES, SEAS.

Náčrt obrázka hviezdice s 5 ramenami a dĺžkou ramena 200

Pozrime sa na postup ako vykresľovať segment SABS. Po vykreslení úsečky SA je potrebné sa otočiťzo smeru AA1 do smeru AA4, t.j. o uhol A1AA4. Z úvahy z predchádzajúceho riešenia vieme o uhloch nasledovné: A1AS = 180°, A1AA3 = A3AS = 90°, A2AA3 = A3AA4 = 360° / počet_ramien,  A1AA2 = 90° - 360° / pocet_ramien. Z toho sa dá vypočítať uhol A1AA4 = 90° + 360° / pocet_ramien. Kružnicový oblúk SA sa vykreslí s pomomerom dlzka_ramien a uhlom 360° / pocet_ramien. Následne je potrebné sa natočiť o uhol BB2S, ktorého veľkosť je 90° + 360° / pocet_ramien. Po tomto natočení sa vykreslí úsečka BS a natočí sa pero o uhol 180°.

Pomocou cyklu sa vykreslia rovnako všetky segmenty hviezdice. Výsledný program na vykreslenie hviezdice so zadaným počtom a dĺžkou ramien a zadanou farbou výplne môže vyzerať napríklad nasledovne:

import turtle


def kresli_hviezdicu(pocet_ramien, dlzka_ramien, farba_vyplne):
    pero.fillcolor(farba_vyplne)
    for _ in range(pocet_ramien):
        pero.begin_fill()
        pero.forward(dlzka_ramien)
        pero.right(90 + 360 / pocet_ramien)
        pero.circle(dlzka_ramien, 360 / pocet_ramien)
        pero.right(90 + 360 / pocet_ramien)
        pero.forward(dlzka_ramien)
        pero.right(180)
        pero.end_fill()


pero = turtle.Turtle()
tabula = turtle.Screen()
kresli_hviezdicu(7, 150, 'lightblue')
tabula.mainloop()

Táto úloha je zameraná na:

  • použitie stratégie riešenia problémov - dekompozíciu problému na podproblémy, hľadanie vzorov, nakreslenie si obrázka,

  • precvičenie príkazov volania funkcií s parametrami, cyklu for, príkazov korytnačej grafiky.

Vaše zaujímavé riešenia a najčastejšie chyby

Do riešenia úlohy sa zapojilo 8 tímov z kategórie EXPERT. Plný počet bodov za svoje riešenie získal len jeden tím raketak, ktorému srdečne gratulujeme. Vačšina riešení najprv vykresľovala zvlášť hviezdicu po obvode a zvlášť ramená zo stredu. Tím procrastinoters vykresľoval pri jednotlivých ramenách aj kružnicové oblúky hviezdice, a to vykresľovaním bielych kruhov z vonkajšej strany.

V riešeniach sme zaregistrovali nasledovné nedostatky, vychádzajúce najčastejšie z nedôslednej analýzy problému:

  • naprogramovanie funkcie bez parametrov alebo len s dvomi parametrami,

  • nevykreslenie, alebo nesprávne vykreslenie kružnicových oblúkov vďaka nesprávnemu výpočtu uhlov kružnicových oblúkov,

  • roztrúsený menej prehľadný zápis hlavného programu, ten sa v Pythone zvykne písať pokope po definíciách funkcií,

  • použitie jednopísmenkových identifikátorov premenných, odporúčame používať zmysluplné názvy premenných (napr. dlzka, pocet, farba).