Materjalid koostas ja kursuse viib läbi
Tartu Ülikooli arvutiteaduse instituudi programmeerimise õpetamise töörühm
< eelmine | 3. nädala sisukord | järgmine > |
3.2 Tsükkel
KORDUV TEGEVUS
Kui püüda arvuti võimalikke plusse välja tuua, siis üheks oluliseks neist on kahtlemata võime mingeid tegevusi kiiresti ja korduvalt sooritada. Nii saab teha arvutusi, midagi andmetest otsida, erinevaid variante läbi vaadata jpm. Arvutid on läinud järjest kiiremaks ja nii saavad paljud asjad tehtud praktiliselt silmapilkselt. Samas on ülesandeid, mille lahendamiseks kulub ikkagi rohkem aega kui tahaks, isegi kui mitu arvutit korraga ülesannet lahendama panna. Näiteks ilmaennustus on selline keeruline ülesanne.
Kui tahta mingeid asju korduvalt teha, siis võivad ju programmid väga pikaks minna? Näiteks kui tahame, et programm väljastaks ekraanile viis korda üksteise alla Tere!
, siis kõlbaks selline programm.
print("Tere!") print("Tere!") print("Tere!") print("Tere!") print("Tere!")
Saja korra jaoks tuleks siis programm vastavalt pikem. Tegelikult on programmeerimiskeeltes olemas head võimalused selliste korduste lühemaks esituseks. Kõigepealt püütakse aru saada, mis on see korduv tegevus, mis päris samasugusena (või kindlate reeglite järgi muudetuna) tuleb ikka ja jälle teha. Selles näites on selleks rida print("Tere!")
. Teise asjana tuleb läbi mõelda, mitu korda me tahame seda tegevust teha. See võib olla meil ette teada, aga võib sõltuda ka mingitest välistest asjaoludest, näiteks kasutaja poolt antud vastusest. Pole ju mõtet parooli uuesti küsida, kui juba õige on sisestatud.
WHILE-TSÜKKEL
Korduvaid tegevusi realiseeritakse tsüklite abil. Vastavaid vahendeid võib konkreetses programmeerimiskeeles olla mitmeid. Näiteks Pythonis on olemas while-tsükkel ja for-tsükkel. Meie alustame eelkontrolliga tsüklist, mille põhimõte on teatud mõttes sarnane valikulausega. Sellist tsüklit kutsutaksegi while-tsükliks, sest reeglina on programmeerimiskeeltes just võtmesõna while selles tähenduses kasutusel. Erinevus if-lausest on selles, et pärast seda, kui tsükli sisus olevad laused on täidetud, minnakse uuesti tingimust kontrollima. Kui tingimus ikka veel kehtib, siis täidetakse sisu edasi jne. Kui mingil hetkel tingimust kontrollides see enam ei kehti, siis lõpetatakse tsükli täitmine. Tsükli sisus olevad laused peavad olema taandatud sarnaselt if-lauses olevatele lausetele.
Eelkontrolliga tsükli plokkskeem näeb välja selline:

Tsükli jätkamistingimus on (nagu ka if-lause tingimus) tõeväärtustüüpi. Kui tingimus on täidetud (tingimusavaldise väärtus on tõene), siis minnakse tsükli sisu täitma, kui aga pole täidetud, siis minnakse tsüklist välja.
Tavaliselt on tingimus esitatud võrdlemisena, aga võib näiteks olla ka lihtsalt tõeväärtus True
. Või hoopis tõeväärtus False
. See viimane on küll üsna mõttetu: nii karm “piirivalvur”, et kunagi kedagi edasi ei lubata. Variandi while True
puhul on tegemist lõpmatu tsükliga, sest tingimusavaldis on alati väärtusega True
. Teoreetiliselt jääbki see tsükkel igavesti tööle. Praktiliselt siiski ilmselt pannakse arvuti millalgi kinni, toimub elektrikatkestus vms. Kui me nüüd Pythonis meelega või kogemata sellise programmi teeme, mis igavesti tööle jääb, siis ei ole meil katkestamiseks siiski vaja arvutit kinni panna. Nimelt saame Thonnys programmitöö katkestada Stop-märgiga nupu või klahvikombinatsiooni Ctrl + F2 abil. (Hoiame all Ctrl-klahvi ja vajutame samaaegselt alla F2-klahvi, mis on klaviatuuri ülemisel real.) (Keskkonnas IDLE katkestatakse programmitöö hoopis Ctrl + C abil.) Tegelikult saab lõpmatut tsüklit kasutada ka päris sihipäraselt sellises olukorras, kus tuleb näiteks midagi aktiivselt oodata. Sellisel juhul on tsüklist väljasaamine teisiti organiseeritud.
Ülesanne
Meie aga tahame ikkagi, et tsükli abil viis korda Tere! ekraanile tuleks. Seega peab olema midagi, mis tsükli sisus muutub nii, et just pärast viiendat korda “piirivalvur” enam tsükli sisu juurde ei luba. Kuidas me inimlikult sellises olukorras loendaksime? Üks võimalus oleks näiteks sõrmedel lugeda ja nii meeles hoida, kui palju kordi juba tehtud. Põhimõtteliselt teeme sarnaselt ka programmeerides. Võtame ühe muutuja, mille nimeks saagu i. Muide just i ongi sageli sellise loendaja nimeks. Olgu i väärtus esialgu 0: i = 0
. Igal tsükli sammul liidame väärtusele 1. Varem olid näited, kus muutujale saime erinevaid väärtusi anda mingite teiste muutujate või näiteks arvude ja tehete abil. Nüüd aga on vaja selle sama muutuja väärtust muuta. Saame seda teha sellise avaldisega
i = i + 1
Võimalik, et selline võimalus vajab natuke harjumist. Kui vaatame koolimatemaatikat, siis võib see paista üsna kummaline, aga võrdusmärgi tähendus on siin natuke teine. Vasak pool näitab, et muutuja i saab uue väärtuse. Paremal pool on avaldis, millega see uus väärtus arvutatakse. Selles arvutamises kasutatakse ka muutuja i senist väärtust. Enne programmi kokkupanekut mõtleme veel jätkamistingimusele. Selleks sobib i < 5
, sest kui i on esialgu 0 ja igal sammul liidetakse 1, siis just 5 sammuga jõuame niikaugele, et tingimus i < 5
ei ole enam täidetud. Panemegi nüüd programmi kokku. Olulisel kohal on taas koolon ja taandamine.
i = 0 while i < 5: print("Tere!") i = i + 1

Püüame nüüd programmi tööd analüüsida sammude kaupa.
- Jätkamistingimus (
i < 5
) on täidetud, kui esimest korda tsükli juurde jõuame, sest 0 < 5. - Pärast esmakordset sisu täitmist on i väärtus 1 ja jätkamistingimus ikkagi täidetud, sest 1 < 5.
- Pärast 2. korda on i väärtus 2 ja ikka saame jätkata, kuna 2 < 5.
- Ja siis i on 3 ja ikka 3 < 5.
- Ja siis i on 4 ja ikka 4 < 5.
- Ja siis i on 5 ja kontrollime, kas i < 5? Kas 5 < 5? Ei ole, sest 5 ja 5 on võrdsed, seega võrratus 5 < 5 ei kehti.
Lisame programmile ühe rea, mis i väärtuse ekraanile tooks, siis saame seda paremini jälgida.
i = 0 while i < 5: print("Tere!") i = i + 1 print(i)
Pange programm tööle.
Kui me programmi alles teeme, siis on mingites kohtades muutujate väärtuste väljastamine täiesti omal kohal, et olla kursis, mis seis vastaval hetkel on. Thonnys on muutuja väärtuste jälgimine sisse ehitatud ja seda saab nähtavale tuua View-menüüst valikuga Variables. Kuna programm töötab kiiresti, siis tavaliselt käivitades jäävad näha ainult programmi töö lõpus kehtivad väärtused. Selleks, et sammsammult programmi tööst ülevaadet saada, tuleb käivitada hoopis silumisrežiimis - putukaga nupuga või Run-menüüst Debug current script. Seejärel saab erineva ulatusega samm teha vastavate nuppude või Run-menüü valikute abil.

Kuna muutuja väärtuse muutmist eelmise väärtuse alusel tuleb päris sagedasti ette, siis on selleks ka lühemad variandid olemas. Näiteks a = a + 3
asemel võime kirjutada a += 3
. Samasugused variandid on ka lahutamise (-), korrutamise (*), jagamise (/), täisarvulise jagamise (//), jäägi leidmise (%) ja astendamise (**) jaoks.
Ülesanne
Ülesanne
Ülesanne
Ülesanne
Ülesanne
Eelmises osas tutvusime kilpkonnagraafikaga ja tegime näiteprogrammina ruudu.
Näiteprogramm. Ruut
from turtle import * # * lisamisel imporditakse kõik kilpkonna käsud forward(100) # Kilpkonn liigub edasi 100 pikslit left(90) # Kilpkonn pöörab 90° vasakule forward(100) # Kordame eelnevaid käske, sest ruudul on neli külge left(90) forward(100) left(90) forward(100) exitonclick() # Saame akna sulgeda hiireklõpsuga
On näha, et kilpkonn peab täitma korduvalt samu käske: minema 100 pikslit edasi ja pöörama seejärel 90° vasakule. Tegemist on tsüklilise tegevusega, seega saame kasutada tsüklit.
Kirjutame programmi ümber nii, et ruut joonistatakse while-tsüklit rakendades.
Näiteprogramm. Ruut II
from turtle import * i = 0 # Muutuja i väärtus on esialgu 0 while i < 4: # Kilpkonn joonistab tsükli abil ruudu. Tsükli keha läbitakse neli korda. forward(100) left(90) i = i + 1 # Muutuja i väärtust suurendatakse ühe võrra exitonclick()
Pange see programm tööle ja püüdke seda modifitseerida nii, et joonistataks hoopis võrdkülgne kolmnurk. Mis sellisel juhul on ruudust erinev? Külgi on kolm ja pöörama peab ... Aga proovige ise!
IGAL SAMMUL JUHTUB MIDAGI
Nagu juba eelmiste näidete puhul oli näha, juhtub igal sammul midagi. Võib juhtuda samu asju, võib natuke erinevaid asju juhtuda. Näiteks "Tere!" väljastamisel juhtus see nii igal sammul. Samuti kilpkonna liikumisel igal tsüklisammul 100 sammu edasi ja 90-kraadine pööre vasakule.
Kui tsüklis oli aga käsk print(i)
, siis igal sammul toimus väljastamine, aga tsüklimuutuja i
väärtus oli sammul erinev. Tsüklimuutuja väärtuse muutumine tagati i = i + 1
(seda oleks võinud ka i += 1
abil saada).
Modifitseerime ruudu joonistamise programmi nii, et igal sammul tehtav sõltuks ka tsüklimuutuja i
tolle hetke väärtusest. Asendame rea forward(100)
reaga forward(100 * i)
. Pange programm palun tööle.
from turtle import * i = 0 # Muutuja i väärtus on esialgu 0 while i < 4: # Tsükli keha läbitakse neli korda. forward(100 * i) left(90) i = i + 1 # Muutuja i väärtust suurendatakse ühe võrra exitonclick()
Muutke programmis tsükli sammude arvu. Selleks tuleb tingimuses i < 4
suurem arv panna. Samuti võib 100 asemel kasutada mõnd väiksemat arvu, et tulemus paremini nähtav oleks.
Tsüklis ei pruugi alati midagi silmnähtavat juhtuda. Näiteks võidakse hoopis mingeid asju "meelde jätta" ja pärast tsüklit kasutada. Nii on järgmises programmis võetud kasutusele muutuja summa
, millesse hakatakse "koguma" summat.
i = 0 summa = 0 while i < 5: summa = summa + i i = i + 1 print(summa)
Ülesanne
Ülesanne
PIKEM SAMM! VÕI HOOPIS LÜHEM?
Eelmistes näidetes on tsüklimuutuja muutunud iga sammuga ühe võrra. See võib küll olla kõige sagedasem variant muidu ka, aga kaugeltki mitte ainus. Põhimõtteliselt saame tsüklimuutujat muuta ükskõik millise lubatud tehtega. Proovige näiteks nii.
i = 0 while i < 5: i = i + 2 print(i)
Võib ka hoopis lühem samm olla i = i + 0.5
. Või hoopis igal sammul kasvab i väärtus kolm korda i = i * 3
. Korrutamise puhul peab küll hoiduma esialgsest väärtusest 0, sest korrutamine seda ei muuda.
Teeme programmi, mis väljastab ekraanile 1, 3, 9, 27 ... . Eelmine tulemus korrutatakse igal sammul kolmega. Kasutajalt küsitakse, millisest arvust peab tulemus väiksemaks jääma.
piir = int(input("Millisest arvust väiksemaks peab tulemus jääma? ")) tulemus = 1 while tulemus < piir: print(tulemus) tulemus = tulemus * 3
Nagu näeme on siin oluliseks muutujaks tulemus ise. Selleks, et lugeda, mitmendal sammul me oleme ja näiteks just sammude arvu piirata, peab kasutusel olema teine muutuja.
piir = int(input("Millisest arvust väiksemaks peab tulemus jääma? ")) tulemus = 1 jrk = 1 while tulemus < piir: print(str(jrk) + ". rida on " + str(tulemus)) tulemus = tulemus * 3 jrk = jrk + 1
Kui nüüd tahta, et arvutataks ainult 6 korda, peaks vastavalt tingimuse asendama:
while tulemus < piir:
asemel while jrk < 7:
.
< eelmine | 3. nädala sisukord | järgmine > |