1.9. Duży Lotek

Przykład Mały Lotek pokazuje, jak wylosować jedną liczbę z zakresu <1; 10> i dać użytkownikowi trzy szanse jej odgadnięcia. Zasady większości gier wymagają typowania wielu liczb z większego zakresu. Napiszemy więc program, w którym poziom trudności odgadywania liczb będzie można dostosować.

Informacja

Przykład „Duży Lotek” pokazuje, jak używać pętli warunkowej do pobierania danych z klawiatury, jak sprawdzać poprawność wprowadzanych danych oraz jak używać list i zbiorów jako złożonych struktur danych.

1.9.1. Zadanie

Napisz program duzy_lotek.py, który losuje n liczb naturalnych z podanego zakresu maks, a następnie pobiera z klawiatury n typów, sprawdza i wypisuje, ile z nich zostało trafionych. Program powinien sprawdzać poprawność podawanych danych wejściowych.

Dane:

  • n – liczba całkowita pobierana z klawiatury,

  • maks – liczba naturalna pobierana z klawiatury większa od n,

  • typ – liczba całkowita pobierana z klawiatury z zakresu <0; maks>.

Wynik – przykładowe komunikaty:

Podaj liczbę losowanych liczb: 4
Podaj maksymalną losowaną liczbę: 10
Wytypuj 4 z 10 liczb:
Podaj liczbę 1: 2
Podaj liczbę 2: 5
Podaj liczbę 3: 7
Podaj liczbę 4: 1

Trafione liczby: {1}
Liczba trafień 1
Wylosowane liczby: [1, 6, 8, 3]

1.9.2. Poprawność danych

Plik duzy_lotek.pyKod nr
 1import random
 2
 3# dane wejściowe
 4error = False
 5try:
 6    n = int(input('Podaj liczbę losowanych liczb: '))
 7    maks = int(input('Podaj maksymalną losowaną liczbę: '))
 8    if n >= maks:
 9        error = True
10except ValueError:
11    error = True
12
13if error:
14    print('Błędne dane!')
15    exit()
16

Podczas pobierania danych z klawiatury lub pliku możemy otrzymać dane niewłaściwego typu, np. ciąg znaków kiedy oczekujemy liczby. Do obsługi tego typu błędów możemy użyć przechwytywania wyjątków (zob. wyjątki). Służy do tego instrukcja try: ... except wyjątek: ..., czyli: spróbuj wykonać kod w bloku try, a w razie błędów przechwyć wyjątek – except wyjątek i wykonaj podporządkowane instrukcje.

W naszym programie jeżeli użytkownik poda łańcuch znaków, którego nie da się zamienić na liczbę całkowitą, instrukcja int() wypisze komunikat invalid literal for int() with base 10 i zgłosi wyjątek ValueError. Wyjątek przechwytujemy i obsługujemy, tj. ustawiamy zmienną pomocniczą error na wartość True (prawda).

Jeżeli typy danych są poprawne możemy sprawdzać, czy otrzymane wartości mieszczą się w odpowiednim zakresie albo zawierają oczekiwane wartości. Korzystamy z instrukcji warunkowej, która w przypadku błędu również zmienia wartość zmiennej error.

Na końcu sprawdzamy, czy zmienna error ma wartość True, co oznacza błąd typu danych lub zakresu wartości. Wypisujemy wtedy odpowiedni komunikat i kończymy program instrukcją exit().

1.9.3. Losowanie liczb

W programie „Mały lotek” losowaliśmy jedną liczbę, którą zapamiętywaliśmy w jednej zmiennej. Tym razem mamy wylosować wiele liczb, które nie powinny się powtarzać. Uzupełniamy więc program:

Plik duzy_lotek.pyKod nr
17# losowanie liczb
18liczby = []
19while len(liczby) < n:
20    liczba = random.randint(0, maks)
21    if liczby.count(liczba) == 0:
22        liczby.append(liczba)
23

Do zapamiętania losowanych liczb używamy listy o nazwie liczby. Losowanie odbywa się w pętli warunkowej dopóki liczba elementów listy jest mniejsza od liczby liczb do wylosowania: while len(liczby) < n:. Wewnątrz pętli wylosowana liczba dodawana jest do listy tylko wtedy, jeżeli w liście nie występuje. Liczbę wystąpień elementu w liście zwraca metoda .count().

Informacja

  • Pętla for nie nadaje się do losowania unikalnych liczb, ponieważ wykonuje się określoną ilość razy, a nie możemy zagwarantować, że losowane liczby będą za każdym razem inne.

  • Ponieważ lista jest sekwencją, warunek liczby.count(liczba) == 0 można zastąpić wyrażeniem liczba not in liczby, w którym korzystamy z zaprzeczonego operatora zawierania not in.

1.9.4. Pobieranie typów

Do pobierania typów z klawiatury użyjemy takiej samej pętli, jak podczas losowania, tzn. wykonuje się ona dopóty użytkownik nie poda tylu poprawnych typów, ile liczb zostało wylosowanych. Uzupełniamy program:

Plik duzy_lotek.pyKod nr
24# pobieranie typów
25print(f'Wytypuj {n} z {maks} liczb: ')
26typy = set()
27error = False
28while len(typy) < n:
29    try:
30        typ = int(input('Podaj typ: '))
31        if typ < 0 or typ > maks or typ in typy:
32            error = True
33    except ValueError:
34        error = True
35
36    if error:
37        print('Błędne dane!')
38        continue
39
40    typy.add(typ)
41

W pętli while kontrolujemy typ pobieranych danych i sprawdzamy:

  • typ < 0 or typ > maks – alternatywa warunków badających czy podany typ jest mniejszy od zera lub większy od wartości maksymalnej,

  • typ in typy – operator zawierania in zwróci prawdę, jeżeli badany typ znajduje się w zbiorze typy.

Jeżeli zmienna error ma wartość True, oznacza to błąd typu danych, zakresu lub powtórzenie typu. Wypisujemy wtedy odpowiedni komunikat i wznawiamy działanie pętli za pomocą instrukcji continue. W przeciwnym razie dodajemy podaną liczbę (typ) do zbioru.

1.9.5. Zbiory

Zbiory (zob. zbiór) to złożone struktury danych, które tym różnią się od list, że zawarte w nich elementy nie mogą się powtarzać i są nieuporządkowane, tzn. nie są indeksowane.

Operacje na zbiorach

  • typy = [] lub typy = set() – utworzenie pustego zbioru,

  • typy.add(element) – dodanie elementu do zbioru,

  • trafione = set(liczby) – utworzenie zbioru z listy,

  • |, -, & – operatory sumy, różnicy i iloczynu (części wspólnej) zabiorów,

  • len(trafione) – zwraca liczbę elementów zbioru.

1.9.6. Liczba trafień

Do programu dopisujemy kod ustalający liczbę trafień i wypisujący dane wyjściowe:

Plik duzy_lotek.pyKod nr
42# sprawdzanie typów i dane wyjściowe
43print()
44trafione = set(liczby) & typy
45if trafione:
46    print(f'Trafione liczby: {trafione}')
47    print(f'Liczba trafień {len(trafione)}')
48else:
49    print('Brak trafień. Spróbuj jeszcze raz!')
50
51print('Wylosowane liczby:', liczby)

Ustalenie liczby trafień w większości języków programowania wymagałoby przeszukiwania listy wylosowanych liczb dla każdego podanego typu. W Pythonie możemy użyć arytmetyki zbiorów, tj. wyznaczamy część wspólną: trafione = set(liczby) & typy.

Jeżeli jakakolwiek liczba została odgadnięta, zbiór trafione jest niepusty i wyrażenie if trafione jest prawdziwe. Wypisujemy wtedy zbiór oraz liczbę jego elementów.

1.9.7. Ćwiczenia

  1. W interpreterze przetestuj poniższe instrukcje:

~$ python3
>>> liczby = [1,3,5,7,9]
>>> typy = set([2,3,4,5,6])
>>> set(liczby) | typy
>>> set(liczby) - typy
>>> trafione = set(liczby) & typy
>>> trafione
>>> len(trafione)
  1. Zmień program tak, aby użytkownik mógł 3 razy podawać typy, tj. odgadywać wylosowane liczby.

    Wskazówka

    Wykorzystaj pętlę for.

  2. Przekształć powtarzający się kod sprawdzający poprawność typu danych na funkcję zwracającą wartość True lub False. Użyj w funkcji w programie odpowiednio go modyfikując.

Poza tym sprawdzamy, czy użytkownik podaje sensowne typy. Warunek if 0 < typ <= maksliczba: to skrócony zapis wyrażenia logicznego z użyciem operatora koniunkcji: typ > 0 and typ <= maksliczba. Sprawdzamy w ten sposób, czy wartość zmiennej typ jest większa od zera i mniejsza lub równa wartości zmiennej maksliczba.

Pojęcia

pętla, lista, zbiór


Licencja Creative Commons Materiały Python 101 udostępniane przez Centrum Edukacji Obywatelskiej na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.

Utworzony:

2026-05-30 o 19:12 w Sphinx 7.3.7

Autorzy:

Robert Bednarz