Materjalid koostas ja kursuse viib läbi
Tartu Ülikooli arvutiteaduse instituudi programmeerimise õpetamise töörühm
< eelmine | 5. OSA sisukord | järgmine > |
5.2 Veel tsüklist
Eelmistes näidetes oli meil tsükli korduste arv juba algul teada. Nüüd aga püüame teha programmi, kus tsükli läbimiste arv sõltub kasutaja sisestatud vastustest. Võtame aluseks valikulause materjali juures olnud programmi, milles küsitakse PIN-koodi. Seal küsiti PIN-koodi üks kord ja lõplik otsus tehti juba ühe pakkumise järel:
print("Sisesta PIN-kood:") sisestatud_pin = input() if sisestatud_pin == "1234": print("Sisenesid pangaautomaati!") else: print("Vale parool! Enesehävitusrežiim aktiveeritud: 3 … 2 … 1 ....")
Tavaliselt siiski antakse ka eksimisvõimalusi ja vale koodi puhul küsitakse uuesti. Püüamegi nüüd selle programmi vastavalt ümber kirjutada. Ilmselt on siin kasu tsüklist. Antud juhul peame tsükliliselt käituma (uuesti küsima) juhul, kui sisestatud PIN-kood ei ole õige. Jätkamistingimuseks sobiks sisestatud_pin != "1234"
, sest me peaks uuesti küsima just siis, kui sisestatud kood ei ole õige. Programm ise oleks näiteks järgmine:
print("Sisesta PIN-kood:") sisestatud_pin = input() while sisestatud_pin != "1234": print("Sisesta PIN-kood:") sisestatud_pin = input() print("Sisenesid pangaautomaati!")
Püüdke samm-sammult läbi mõelda, kuidas selline programm töötab. Vajadusel joonistage selle plokkskeem. Proovige see programm tööle panna ja testige erinevate PIN-koodidega. Proovige ka oma pangakaardi tegeliku koodiga! :-) Või ärge ikka proovige!
Programmi vaadates näeme, et järgmine lõik on kahes kohas.
print("Sisesta PIN-kood:") sisestatud_pin = input()
Võime proovida tsükli eest selle lõigu ära jätta:
while sisestatud_pin != "1234": print("Sisesta PIN-kood:") sisestatud_pin = input() print("Sisenesid pangaautomaati!")
Sellisel juhul aga tuleb veateade, sest muutujal sisestatud_pin ei ole väärtust, kui seda while-tingimuses esimest korda kontrollida tahetakse.
Traceback (most recent call last): File "C:/Python33/pin.py", line 1, in <module> while sisestatud_pin != "1234": NameError: name 'sisestatud_pin' is not defined
Anname muutujale sisestatud_pin esialgseks väärtuseks tühja sõne. Sellega garanteerime, et muutujal sisestatud_pin on väärtus ja while jätkamistingimus on esialgu kindlasti tõene, sest tühi sõne ei ole võrdne sõnega "1234".
sisestatud_pin = "" while sisestatud_pin != "1234": print("Sisesta PIN-kood:") sisestatud_pin = input() print("Sisenesid pangaautomaati!")
Nüüd ei pääse ilma parooli sisestamata edasi. Paraku on süsteem ebaturvaline, sest katsetada saab suvaline arv kordi. Püüame ka katsete arvu piirata:
sisestatud_pin = "" katseid = 3 while sisestatud_pin != "1234" and katseid > 0: print("Sisesta PIN-kood:") print("Jäänud on " + str(katseid) + " katset.") katseid -= 1 sisestatud_pin = input() print("Sisenesid pangaautomaati!")
Nüüd koosneb jätkamistingimus kahest osast - endiselt kontrollitakse, kas sisestatud PIN-kood on vale, aga lisaks kontrollitakse veel ka seda, mitu korda veel vastata saaks. Enne tsüklit on kordade arvuks määratud 3 ja pärast igat tsükli keha täitmist väheneb see arv 1 võrra. Esimesel korral saab muutuja katseid väärtuseks 2, teisel korral 1 ja kolmandal korral 0.
Jätkamistingimuses kasutatakse võtmesõna and, mis tähendab, et tingimuse kehtimiseks peab nii selles sõnast paremal pool kui vasakul pool olev tingimus tõene olema, teisisõnu peavad mõlemad osaavaldised olema tõesed. Tõesti, selleks et PIN-koodi peaks uuesti küsima, ei tohi olla veel õiget sisestatud ja järelejäänud katseid peab olema rohkem kui 0.
Kui eelnevas näites midagi segaseks jäi, siis saab vaadata kokkuvõtvat videot programmi koostamise kohta:
Ülesanne
Mure on nüüd selles, et küsimiste arv on küll piiratud, aga isegi kui valet koodi kolm korda sisestatakse, saadakse ikka pangaautomaati sisse. Muudame programmi nii, et arvestataks, kas lõpuks sisestati õige kood või mitte. Kui ei sisestatud, siis on kuri karjas ja lahkumiseks antakse 10 sekundit! :-) Programmi saab üheks sekundiks "uinutada" käsu sleep(1)
abil, kuid selle kasutamiseks tuleb programmi algusesse lisada rida from time import sleep
, mis ütleb Pythonile, et järgnevas programmis kasutatakse funktsiooni sleep()
, mis pärineb moodulist time
.
from time import sleep sisestatud_pin = "" katseid = 3 while sisestatud_pin != "1234" and katseid > 0: print("Sisesta PIN-kood:") print("Jäänud on " + str(katseid) + " katset.") katseid -= 1 sisestatud_pin = input() if sisestatud_pin == "1234": print("Sisenesid pangaautomaati!") else: print("Enesehävitusrežiim aktiveeritud:") i = 10 while i > 0: print(i) i -= 1 sleep(1)
Soovijad võiksid mõtiskleda ja katsetada, mida teeks programm teisiti, kui
if sisestatud_pin == "1234":
asemel oleks
if katseid > 0:
Eelmises programmis oli viimane tsükkel valikulause else-osa sees. Näeme, et taane on vastavalt läinud veel kaugemale. Selline mitmetasemeline struktuur on programmides täiesti tavaline. Vabalt võib olla ka näiteks if-lause while-tsükli sees.
Klassikalises arvamismängus see nii ongi.
from random import randint arv = randint(1,19) # juhuslik täisarv print("Mõtlen ühele 20-st väiksemale naturaalarvule. Arva ära!") arvamus = int(input()) while arvamus != arv: if arv > arvamus: print("Minu arv on suurem!") else: print("Minu arv on väiksem!") print("Arva veel!") arvamus = int(input()) print("Õige! Tubli!")
Näites oli kasutatud ka tühje ridu, et inimesel oleks programmi lihtsam lugeda. Python tühje ridu ei arvesta. Samuti ei arvesta Python # järel olevaid kommentaare.
Pange mäng tööle ja mängige, aga ärge sellest sõltuvusse sattuge! Proovige mängu modifitseerida. Näiteks las programm loeb vastamiste arvu ka ja annab reaktsiooni vastavalt sellele. (Kui arvatakse arv esimese korraga, siis näiteks võiks mängijal soovitada oma selgeltnägija võimeid ehk laiemaltki kasutada.) Huvitav oleks ka teistpidi ülesanne, kus arvuti on arvaja osas ja arvab võimalikult mõistliku strateegiaga.
Ülesanne
Mõelda oma elule ja ümbritsevale ning kirjeldada ühte tsüklilist protsessi. Seejuures märkida, kas tsükli läbimiste arv on enne teada või selgub täitmise ajal. Protsess ei pea olema programmeeritav. Lahendus esitada Moodle'is vastava testiküsimuse vastusena.
< eelmine | 5. OSA sisukord | järgmine > |