Wyjątek ValueError a pętla for

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')
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

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')
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.

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')
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ąć.

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)

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