Wyjątek ValueError a pętla for

Odpowiedz Nowy wątek
2019-06-08 14:52
0

Cześć. Na początku chciałbym się przywitać bo to mój pierwszy post. :)

Napisałem krótki quiz z tabliczki mnożenia. Pięć pytań, licznik punktów, itd.
W odpowiedzi należy podać liczbę, ale liczę się z tym, że ktoś może wpisać coś innego, więc nie chcę, żeby wyskakiwał mi błąd, dlatego chciałem dodać wyjątek "ValueError".
Próbowałem w niego wsadzić całą pętlę, ale po wpisaniu pięciokrotnie błędu pętla się kończy i tyle. Chciałbym, żeby zadawało pytanie dopóki użytkownik nie wpisze liczby.

import random

points = 0

for answers in range(0, 5):
    numberA = random.randint(1, 10)
    numberB = random.randint(1, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    answer = int(input('Odpowiedź: '))
    if answer == result:
        points+=1
        print('Dobrze! Zdobyłeś punkt!')
    else:
        print('Błąd!')
print('Twój wynik to:', str(points) +'/5 punktów')

@Edit:

Chyba dałem radę w inny sposób, ale jakoś nie jestem do tego przekonany.

import random

points = 0
a = 1

while a <= 5:
    numberA = random.randint(1, 10)
    numberB = random.randint(1, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    try:
        answer = int(input('Odpowiedź: '))
        if answer == result:
            points+=1
            a+=1
            print('Dobrze! Zdobyłeś punkt!')
        else:
            a+=1
            print('Błąd!')
    except ValueError:
        print('Nieprawidłowa wartość!')
        continue
print('Twój wynik to:', str(points) +'/5 punktów')
edytowany 1x, ostatnio: Sevy, 2019-06-08 15:26

Pozostało 580 znaków

2019-06-08 18:25
1

Ładniej i czytelniej by było jakbyś stworzył funkcję do pobierania odpowiedzi użytkownika i to w niej zawarł właśnie wyjątek

Pozostało 580 znaków

2019-06-08 23:08
sig
2

Ja bym w przypadku podania nie inta zapytał jeszcze raz, i o mnożenie przez jeden nie pytał. Dodatkowo for zamiast twojego while

import random

points = 0

for a in range(5):
    numberA = random.randint(2, 10)
    numberB = random.randint(2, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    while 1:
        try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

print('Twój wynik to:', str(points) +'/5 punktów')
edytowany 2x, ostatnio: sig, 2019-06-08 23:12

Pozostało 580 znaków

2019-06-09 14:57
0
sig napisał(a):

Ja bym w przypadku podania nie inta zapytał jeszcze raz, i o mnożenie przez jeden nie pytał. Dodatkowo for zamiast twojego while

import random

points = 0

for a in range(5):
    numberA = random.randint(2, 10)
    numberB = random.randint(2, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    while 1:
        try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

print('Twój wynik to:', str(points) +'/5 punktów')

@sig
jestem 'noobem' w programowanie dlatego pytam.
Czy jeśli zmieniłeś pętle while na for to zwiększanie zmiennej a nie traci sensu? pętla for chyba i tak wykona się 5 razy?

Pytam bo nie wiem, czy to przeoczenie, czy ja czegoś nie rozumiem.

Słusznie zauważyłeś, czasem przerabiając cudze kody pomija się takie fragmenty, po prostu zmieniasz fragmenty interesujące cię w perspektywie problemu, nie żeby go całego przerabiać i usuwać zbędne rzeczy. To z reguły pozostaje pytającemu zauważyć, jak tobie słusznie się udało :) - Guaz 2019-06-09 16:41

Pozostało 580 znaków

2019-06-09 16:39
0

co tu robi while 1? jak on działa?

sig napisał(a):

Ja bym w przypadku podania nie inta zapytał jeszcze raz, i o mnożenie przez jeden nie pytał. Dodatkowo for zamiast twojego while

import random

points = 0

for a in range(5):
    numberA = random.randint(2, 10)
    numberB = random.randint(2, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    while 1:
        try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

print('Twój wynik to:', str(points) +'/5 punktów')
while 1: to tyle samo co while True:, bardzo popularny zapis dla piszących w C (? Tak coś mi świta). Jest to nieskończona pętla, kończy się tylko i wyłącznie jak dojdzie do kodu break. - Guaz 2019-06-09 17:11
Znam ją faktycznie z c++, ale jest chyba popularna w wszystkich językach. - sig 2019-06-09 17:18
PS: Jeszcze skończy się ta pętla w wyniku błędu którego nie przechwycisz poprzez try/except, oraz kilka bardziej zaawansowanych rzeczy z wątkami. No względnie tak, chociaż o ile pamięć mnie nie myli w Javie nie ma bata, while (1): nie zadziała :D. Ogólnie można tak pisać, nie jest to żaden błąd, ot początkowy zamysł while (warunek) jest najczytelniejsze, natomiast True/False z reguły zwracają wszelkie warunki. Ale w pythonie to i tak można robić cuda, dawać while (lista) a wewnątrz pętli usuwać elementy ;d. Jak struktura będzie pusta, to zostanie zrzutuowana na False. - Guaz 2019-06-09 17:24
Kolejna pozostałość po jego kodzie, zwykle w takich przypadkach stosuję samo except bez "kategorii". - sig 2019-06-09 19:20

Pozostało 580 znaków

2019-06-09 17:22
sig
0

Skoro już poprawiamy, to może by tak w przypadku błędu podać prawidłową odpowiedź? Użytkownik szybciej się nauczy. A także pytać aż poda 5 poprawnych odpowiedzi, i podać mu ilu prób potrzebował żeby to osiągnąć.

Pozostało 580 znaków

2019-06-09 21:33
2

Kilka uwag co do kodu.

Po 1. staramy się zawsze żeby wyjątki obejmowały tylko obszar kodu, w którym ten wyjątek faktycznie może wystąpić.

Więc kod

       try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

zamieniamy na np.

        try:
            answer = int(input('Odpowiedź: '))
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')
            continue

        if answer == result:
            points+=1
            a+=1
            print('Dobrze! Zdobyłeś punkt!')
        else:
            a+=1
            print('Błąd!')
        break

Co też można pozmieniać. Po 1. zmienna a już nie będzie potrzebna. Po 2. można skorzystać tu z funkcji. Zmienić nazwy zmiennych. numberA zmienić albo na numer_a albo na samo a. Jednoliterowe zmienne generalnie są potępiane ale w tym przypadku mogę być zastosowane bo są jednoznaczne.
Możemy skorzystać z formatowania tekstu zamiast kleić string jak w czasach prehistorycznych czyli:

print('Ile to jest', a ,'razy', str(b) + '?') zmieniamy na np. print(f'Ile to jest {a} razy {b}?') lub korzystamy z format jeśli nie nasza wersja Pythona nie wspiera f-stringów.

Więc poprawiony kod mógłby wyglądać tak:

import random

points = 0

def get_answer():
    while True:
        try:
            return int(input('Odpowiedź: '))
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

for _ in range(5):
    a = random.randint(2, 10)
    b = random.randint(2, 10)
    result = a * b

    print(f'Ile to jest {a} razy {b}?')
    answer = get_answer()

    if answer == result:
        points += 1
        print('Dobrze! Zdobyłeś punkt!')
    else:
        print('Błąd!')

print(f'Twój wynik to: {points}/5 punktów')

Dodatkowo można by jeszcze pokusić się o dodatkową zmienną przechowującą ile prób powinien mieć użytkownik. Chodzi tu o liczbę 5 bo jest ona dosyć magiczna (magic number). Wtedy w jednym miejscu zmieniamy ile użytkownik ma prób. Aktualnie żeby z 5 zrobić 6 musisz to zmienić w dwóch miejscach (w pętli oraz przy wyświetleniu wyników)

edytowany 2x, ostatnio: anonimowy, 2019-06-09 21:36

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0