Lekcja 6 - pętla while, warunki, break (notatki)

Lekcja 6 - pętla while, warunki, break (notatki)

Moduł turtle cz.2

Przy tworzeniu grafik za pomocą żółwika można korzystać z wielu pętli naraz dzięki czemu uzyskamy bardziej skomplikowane wzory

Podstawą jest kod tworzący kwadraty w kwadratach, rozbudowany o element skrętu żółwia i powtórzony 4 krotnie.

rozmiar = 80
ilosc_kwadratow = 4
for _ in range(4):
    for x in range(ilosc_kwadratow):
        for y in range(4):
            zolwik.forward(rozmiar)
            zolwik.left(90)
        rozmiar += 20
    zolwik.left(90)
    rozmiar = 80

Opierając się na wzorze dla wieloboków można stworzyć także spirale.

ilosc_scianek = 6
skret = 360 / ilosc_scianek - 0.5
dlugosc_boku = 6
for _ in range(400):
    zolwik.forward(dlugosc_boku)
    dlugosc_boku +=2
    zolwik.left(skret)

Powstaje spirala

Kod można uprościć jeśli wykorzystamy wszystkie możliwości jakie daje nam funkcja range.

for i in range(6, 600, 2):
  zolwik.forward(i)
  zolwik.left(59.5)

Powstaje spirala. "i" dzięki range najpierw ma wartość 6, po przejściu pętli 8, przy następnej 10 itd. (Patrz poprzednie zajęcia dotyczące range).

W żółwiku można zmieniać także kolor rysowanej linii w trakcie rysowania. W tym celu należy skorzystać z funkcji random. Po zaimportowaniu tego modułu do naszego pliku, trzeba wstawić listę kolorów używając nazewnictwa zgodnego ze schematem (patrz).

import random
kolory = ["CornflowerBlue",
    "DarkOrchid",
    "IndianRed",
    "DeepSkyBlue",
    "LightSeaGreen",
    "wheat",
    "SlateGray",
    "SeaGreen",
]

for i in range(6, 600, 2):
  zolwik.pencolor(random.choice(kolory))
  zolwik.forward(i)
  zolwik.left(59.5)

Pętla while

Pętla która wykonuje się tak długo jak dany warunek jest spełniany (czyli zwraca nam prawdę). Jeśli po drodze warunek się zmieni pętla się zatrzymuje.

i = 0

while i < 10
  print(i)
  i += 1

Jeśli warunek jest skonstruowany nieprawidłowo to pętla będzie trwać w nieskończoność.

i = 0

while i < 10
  print(i)
  i -= 1

Pętla będzie trwać w nieskończoność.

W takim wypadku konieczne jest "siłowe" zatrzymanie programu poprzez równoczesne wciśnięcie ctrl + c.

W ten sposób możemy na użytkowniku wymusić wykonanie koniecznego działania

haslo = "haslo1234"

wprowadzone = ""
while wprowadzone != haslo:
  wprowadzone = input("wprowadź właściwe hasło: ")

print("Koniec programu")

Bez wprowadzenia konkretnego hasła program cały czas będzie żądał jego wprowadzenia.

punkty = 0

print('''
Pytanie
a
b
c
""")

wybor_uzytkownika = input("Wybierz dobrą dopowiedź a, b lub c: ")

while wybor_uzytkownika not in ("a", "b", "c")
  print("Zły wybór, spróbuj jeszcze raz.")
  wybor_uzytkownika = input("Wybierz a, b lub c: ")

if wybor_uzytkownika == "c"
  punkty+=1

print(f"Twoje punkty to: {punkty}")

Podobne rozwiązanie można zastosować np. w quizie. To rozwiązanie wymusza na użytkowniku dokonanie wybory spośród 3 opcji: "a", "b" lub "c". Wpisanie każdej innej odpowiedzi wywoła użycie pętli while.

x = 0
while True:
  x = x + 1
  print(x)

Przykład pętli nieskończonej

Nieskończone pętle mogą być stosowane świadomie np. przy działaniach różnego rodzaju programów. Zawsze jednak musi być sposób na wyjście z pętli, temu służy funkcja break.

Break

Funkcja break zmusza pętle while do zatrzymania. Przeważnie połączona jest z inną pętlą, tak by zatrzymać program po spełnieniu określonego warunku:

i = 100

while True:
  print(i)
  if i == 0:
    break
  i -= 1

Pętla while zatrzyma się gdy wartość "i" spadnie ze 100 do 0.

x = 0

while True:
  x = x + 1
  print(x)
  if x == 99:
    break

Pętla while zatrzyma się gdy wartość "x" urośnie do 100.

Wykorzystując pętle while można odtworzyć każde zachowanie pętli for, ale jego wykonanie może zająć więcej czasu (to jednak nie działa na odwrót) i wymaga wprowadzenia dodatkowych zmiennych. Przyjrzyjmy się jak za pomocą pętli while stworzyć kwadrat (patrz dla porównania wzór z użyciem if).

i = 0
while i < 4:
    zolwik.forward(100)
    zolwik.right(90)
    i +=1

Konieczne jest wprowadzenie dodatkowej zmiennej "i" by "policzyć" powtórzenia. Inaczej żółwik wiecznie rysowałby kwadraty.

Podobnie jest w przypadku np. wzorów na wielokąty:

ilosc_scianek = 6
skret = 360 / ilosc_scianek
dlugosc_boku = 50
i = 0
while i < ilosc_scianek:
    zolwik.forward(dlugosc_boku)
    zolwik.left(skret)
    i += 1

Ponownie trzeba wprowadzić dodatkową zmienną ("i"), która zatrzyma nam wykonywanie pętli while.

Pamiętaj, że funkcja while zadziała tylko gdy warunek jest prawdziwy. W pozostałych wypadkach, nie wykona się.

x = 0
while False:
  x = x + 1
  print(x)

Wynik: nie wyświetli się nic. Ponieważ warunek do pętli jest fałszywy, więc pętla się nie wykona.

x = 0
while False:
  x = x + 1
print(x)

Wyświetli się 0. Dlaczego? Pamiętajmy o wcięciach. W tym wypadku print działa niezależnie od pętli while.

n = 5
while n:
  n = n - 1
  print(n, end=" ")

Wyświetli się: 4 3 2 1 0. Ponieważ przy pierwszym przejściu pętli wartość "n" najpierw zostanie zmniejszona o 1, potem wyświetlona na ekranie jako "4". Potem odpowiednio "3", "2", "1". Przy ostatnim powtórzeniu zostanie zmniejszona do 0. Potem zaś pętla się zatrzyma ponieważ warunek będzie fałszywy. (Fałsz ma wartość 0).

Ćwiczenia

Stwórz Ciąg Fibonacciego czyli ciąg liczb naturalnych określony w następujący sposób: pierwszy wyraz jest równy 0, drugi jest równy 1, a każdy kolejny jest sumą dwóch poprzednich: 0 1 1 2 3 5 8 itd.

lista = [0, 1]
pulap = 50
suma_ostatnich = lista[-1] + lista[-2]
while suma_ostatnich < pulap:
  lista.append(suma_ostatnich)
  suma_ostatnich = lista[-1] + lista[-2]
print(lista)

Wynik: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34].

Wykorzystaj ciąg Fibonacciego by stworzyć za pomocą modułu turtle ciąg kwadratów powiększający się właśnie o kolejne liczby z tego ciągu. Dodatkowo pokoloruj je na losowe kolory. Zgodnie z obrazkiem:

import turtle
import random

zolwik = turtle.Turtle()
zolwik.speed(5)
zolwik.shape("turtle")

lista = [0, 1]
pulap = 50
suma_ostatnich = lista[-1] + lista[-2]
dl_boku = 10
kolory = [
    "CornflowerBlue",
    "DarkOrchid",
    "IndianRed",
    "DeepSkyBlue",
    "LightSeaGreen",
    "wheat",
    "SlateGray",
    "SeaGreen",
]

while suma_ostatnich < pulap:
  lista.append(suma_ostatnich)
  suma_ostatnich = lista[-1] + lista[-2]

for element in lista[1:]:
  zolwik.fillcolor(random.choice(kolory))
  zolwik.begin_fill()
  for _ in range(4):
      zolwik.forward(dl_boku*element)
      zolwik.left(90)
  zolwik.end_fill()
  zolwik.forward(dl_boku*element)
  zolwik.left(90)
  zolwik.forward(dl_boku*element)
turtle.exitonclick()

Dokonując niewielkiej zmiany w kodzie można sprawić by zółwik pokolorował tylko część kwadratów

for element in lista[1:]:
  zolwik.fillcolor(random.choice(kolory))
  zolwik.begin_fill()
  for _ in range(6):
      zolwik.forward(dl_boku*element)
      zolwik.left(90)
  zolwik.right(90)  
  zolwik.end_fill()

Zadanie domowe

1) Stwórz błądzenie losowe żółwika stosując się do kilku zasad: 1) Żółwik przemieszcza się o stałą odległość (30); 2) Może skręcać o 90, 180, 270 lub 360 stopni; 3) Może wchodzić na swoją ostatnią ścieżkę; oraz 4) losowo zmienia kolor linii.

import turtle
import random

zolwik = turtle.Turtle()
zolwik.speed(7)
zolwik.shape("turtle")
zolwik.pensize(3)
screen=turtle.Screen()
screen.setup(1920,1080)

kolory = [
    "CornflowerBlue",
    "DarkOrchid",
    "IndianRed",
    "DeepSkyBlue",
    "LightSeaGreen",
    "wheat",
    "SlateGray",
    "SeaGreen",
]
dl_boku = 30
kat = (90, 180, 270, 360)
while True:
    zolwik.pencolor(random.choice(kolory))
    zolwik.forward(dl_boku)
    zolwik.left(random.choice(kat))
turtle.exitonclick()
  1. Refakturuj quiz wzbogacając go o pętle for i while oraz losowy wybór
import random

pytania = {
    "Kiedy odbyła się bitwa pod Grunwaldem?": [
        "1410", "1454", "1310", "1267",
    ],
    "Kiedy wybuchła druga wojna światowa?": [
        "1939", "1918", "1914", "1941",
    ],
    "Kiedy wybrano Polaka na papieża?": [
        "1978", "1987", "1992", "1982"]
}
gracz = input("Podaj swoje imię: ")
print(f"Witaj {gracz}!")
wynik = 0
ranking = {}
ranking[gracz] = wynik

for klucz_pytanie, war_odpowiedzi in pytania.items():
    prawidlowa_odp = war_odpowiedzi[0]
    print(klucz_pytanie)
    alternatywy = random.sample(war_odpowiedzi, k=4)
    print(alternatywy[0])
    print(alternatywy[1])
    print(alternatywy[2])
    print(alternatywy[3])
    odpowiedz = input("Twoja odpowiedź to: ")

    while odpowiedz not in (war_odpowiedzi):
      print("Zły wybór, spróbuj jeszcze raz.")
      odpowiedz = input("Twoja odpowiedź to: ")

    if odpowiedz == prawidlowa_odp:
        wynik +=1
        print("Brawo!")
    else:
        print("Pudło!")

print(f"Twój wynik {gracz} to {wynik}")
print("\n---Wyniki---")
for gracz, wynik in ranking.items():
    print(f"{gracz} zdobył {wynik}")

Udało mi się uzyskać losowe wyświetlanie odpowiedzi, ale nie chce mi losować pytań 🙁

C.d. Refaktoryzacji quizu w lekcji 7.