Schleife

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
KiliNein
User
Beiträge: 1
Registriert: Dienstag 23. April 2019, 03:27

Also ich hätte mal eine Frage: wie kann ich meinen Code von der zweiten Zeile an wieder ausführen bis eine bestimmte Bedingung erreicht ist hier kurz mein Code:

from random import randint
a = (randint(0, 100))
if a < 75:
e = 1
print("Common Helmet")
elif a < 90 and a > 75:
e = 2
print("Rare Helmet")
elif a < 99 and a > 90:
e = 4
print("Epic Helmet")
elif a == 100:
e = 6
print("Legendary Helmet")
b = (randint(0, 100))
if e == 1:
pass
elif e == 2:
pass
elif e == 4:
pass
elif e == 6:
pass
if b < 75:
f = 1
print("Common Chestplate")
elif b < 90 and b > 75:
f = 2
print("Rare Chestplate")
elif b < 99 and b > 90:
f = 4
print("Epic Chestplate")
elif b == 100:
f = 6
print("Legendary Chestplate")
if f == 1:
pass
elif f == 2:
pass
elif f == 4:
pass
elif f == 6:
pass
c = (randint(0, 100))
if c < 75:
g = 1
print("Common Leggins")
elif c < 90 and c > 75:
g = 2
print("Rare Leggins")
elif c < 99 and c > 90:
g = 4
print("Epic Leggins")
elif c == 100:
g = 6
print("Legendary Leggins")
if g == 1:
pass
elif g == 2:
pass
elif g == 4:
pass
elif g == 6:
pass
d = (randint(0, 100))
if d < 75:
h = 1
print("Common Boots")
elif d < 90 and d > 75:
h = 2
print("Rare Boots")
elif d < 99 and d > 90:
h = 4
print("Epic Boots")
elif d == 100:
h = 6
print("Legendary Boots")
if h == 1:
pass
elif h == 2:
pass
elif h == 4:
pass
elif h == 6:
pass
j = e + f + g + h
if j < 6:
i = 1
print(">Bad Loot<")
elif j < 9 and j > 5:
i = 2
print("[Okay Loot]")
elif j < 13 and j > 8:
i = 3
print("*Good Loot*")
elif j < 100 and j > 12:
i = 4
print("{Epic Loot}")

Es ist eine Art Kisten-Simulator welchen ich simulieren möchte also so lange Ergebnisse Angezeigt bekommen möchte bis j = 24 also alles auf "Legendary" ist. Wie ist dies möglich oder ist dies überhaupt möglich? Die Pass Lines von e, f, g, und h sind später noch für Soundfiles also jetzt nur für j wichtig
Benutze Visual Studio Code bin leider ein Anfänger aber hoffe bald und durch eure Hilfe besser zu werden. Danke schonmal.
bb1898
User
Beiträge: 200
Registriert: Mittwoch 12. Juli 2006, 14:28

Leider wird Dir so niemand antworten können, weil die verlorenen Einrückungen Dein Programm unverständlich machen. Setz den Programmtext doch bitte in Code-Tags:

Code: Alles auswählen

if 7 < 3:
    print("Wer hat denn da die natürlichen Zahlen kaputt gemacht?")
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@KiliNein: Zwei Sachen die Du Dir ganz schnell wieder abgewöhnen solltest ist Code kopieren, einfügen, und geringfügig ändern. Und einbuchstabige Namen die gar nichts aussagen.

Als nächstes würde ich dann dringend von magischen Zahlen abraten, also das 1 für „Common“, 2 für „Rare“, und so weiter steht. Das ist sehr unübersichtlich. Man kann sich dafür Konstanten definieren um es etwas lesbarer zu machen. Besser wäre das `enum`-Modul.

Deine Spielobjekte sind zusammengesetze Werte aus der ”Klasse”, also so einem eben beschriebenen `Enum`-Wert, und der Beschreibung was es ist ('Helmet', …) also sollte man sich dafür auch einen zusammengesetzen Wert erstellen. Am einfachsten ein Tupel, besser ein `collections.namedtuple()`.

Auch für die Endbewertung könnte man sich ein `Enum` erstellen.

Bei den Tests auf Grenzen verbindest Du immer zwei Tests gegen die gleiche Variable mit ``and`` – da würde man eher die Operatoren verketten. Also statt ``d < 90 and d > 75`` würde man ``75 < d < 90`` schreiben. Und da hast Du auch einen Fehler im Programm denn bei den Tests auf kleiner/grösser vergisst Du immer was passieren soll wenn der Wert mal *gleich* einem Vergleichswert sein sollte.

Wiederholen kann man Code mit Schleifen. Du suchst hier wohl eine ``while``-Schleife. Besser gesagt eine ”Endlosschleife” (``while True:``) die mit ``break`` abgebrochen werden kann wenn die Abbruchbedingung innerhalb der Schleife erreicht ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

KiliNein hat geschrieben: Dienstag 23. April 2019, 03:36 Es ist eine Art Kisten-Simulator welchen ich simulieren möchte also so lange Ergebnisse Angezeigt bekommen möchte bis j = 24 also alles auf "Legendary" ist. Wie ist dies möglich oder ist dies überhaupt möglich?
Solange j ungleich 24 ist möchtest du den Code wiederholen?

Das übersetzt sich fast wörtlich in

Code: Alles auswählen

while j != 24:
Die Verwendung von while findet sich im Tutorial sehr weit vorne unter First Steps towards Programming. Zur Sinnhaftigkeit von einbuchstabigen Variablennamen hat __blackjack__ ja schon etwas gesagt.

Bei der Gelegenheit noch eine Anmerkung zu deinen Vergleichen. Da gibt es eine übersichtlichere Variante:

Code: Alles auswählen

# dein Code
elif a < 90 and a > 75

# besser lesbar
elif 75 < a < 90
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Programmieren bedeutet auch, ein Problem zu abstrahieren, statt alles ausführlich hinzuschreiben.
Hier also, dass Du verschiedene Gegenstände hast, für jeden Gegenstand aber das selbe machst.

Code: Alles auswählen

from random import randint

ATTRIBUTES = [
    (75, 1, 'Common'),
    (90, 2, 'Rare'),
    (99, 4, 'Epic'),
    (100, 6, 'Legendary'),
]

LOOT_VALUES = [
    (5, '>Bad Loot<'),
    (8, '[Okay Loot]'),
    (12, '*Good Loot*'),
    (24, '{Epic Loot}'),
]

ITEMS = ["Helmet", "Chestplate", "Leggins", "Boots"]

def roll():
    a = randint(0, ATTRIBUTES[-1][0])
    for boundary, loot, attribute in ATTRIBUTES:
        if a <= boundary:
            return loot, attribute
    assert False, "never reached"

def fill_box():
    total_loot = 0
    for item in ITEMS:
        loot, attribute = roll()
        print(f"{attribute} {item}")
        total_loot += loot

    for value, loot in LOOT_VALUES:
        if total_loot <= value:
            print(loot)
            break
    return total_loot

if __name__ == '__main__':
    fill_box()
Der nächste Schritt wäre, so lange Boxen zu füllen, bis Du die gewünschte hast.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hier mal eine Umsetzung der meisten meiner Anmerkungen in Code:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple
from enum import Enum
from random import randint


class ItemClass(Enum):
    COMMON = 1
    RARE = 2
    EPIC = 4
    LEGENDARY = 6
    
    @staticmethod
    def random():
        random_value = randint(0, 100)
        if random_value < 75: 
            result = ItemClass.COMMON
        elif random_value < 90:
            result = ItemClass.RARE
        elif random_value < 99:
            result = ItemClass.EPIC
        elif random_value == 100:    
            result = ItemClass.LEGENDARY
        else:
            assert False, random_value
        
        return result


Item = namedtuple(Item, 'class_ name')


def get_random_thing(name):
    return Item(ItemClass.random(), name)


def print_item(item):
    print(f'{item.class_.title()} {item.name}')


def main():
    while  True:
        items = [
            get_random_thing(name)
            for name in ['Helmet', 'Chestplate', 'Leggins', 'Boots']
        ]
        
        for item in items:
            print_item(item)
        
        items_value = sum(item.class_.value for item in items)
        if items_value < 6:
            print('>Bad Loot<')
        elif items_value < 9:
            print('[Okay Loot]')
        elif items_value < 13:
            print('*Good Loot*')
        else:
            print('{Epic Loot}')

        if all(item.class_ == ItemClass.LEGENDARY for item in items):
            break


if __name__ == "__main__":
    main()
Die Abbruchbedingung habe ich nicht als Summe und Vergleich mit einer Zahl gemacht, sondern so das man einfacher ablesen kann was das Abbruchkriterium eigentlich bedeutet.

Ich habe hier auch nirgends eine verkettete Bedingung oder ``and`` bei den Bereichsvergleichen, weil die jeweils zusätzliche Bedingung die Du da hattest, im Grunde bereits durch den ``if``/``elif``-Zweig davor abgedeckt war.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und nun überarbeitet und in lauffähig:

Code: Alles auswählen

#!/usr/bin/env python3
from enum import Enum
from random import randint

from attr import attrib, attrs


class ItemClass(Enum):
    COMMON = (1, 74)
    RARE = (2, 89)
    EPIC = (4, 98)
    LEGENDARY = (6, 100)
    
    def __init__(self, item_value, probability):
        self.item_value = item_value
        self.probability = probability
    
    @classmethod
    def random(cls):
        random_value = randint(0, 100)
        for class_ in cls:
            if random_value <= class_.probability:
                return class_
        
        assert False, random_value


@attrs
class Item:
    class_ = attrib()
    name = attrib()
    
    def __str__(self):
        return f'{self.class_.name.title()} {self.name}'
    
    @property
    def value(self):
        return self.class_.item_value
    
    @classmethod
    def random_classed(cls, name):
        return cls(ItemClass.random(), name)


def main():
    while  True:
        items = [
            Item.random_classed(name)
            for name in ['Helmet', 'Chestplate', 'Leggins', 'Boots']
        ]
        
        for item in items:
            print(item)
        
        items_value = sum(item.value for item in items)
        if items_value < 6:
            print('>Bad Loot<')
        elif items_value < 9:
            print('[Okay Loot]')
        elif items_value < 13:
            print('*Good Loot*')
        else:
            print('{Epic Loot}')
        
        print()
        
        if all(item.class_ == ItemClass.LEGENDARY for item in items):
            break


if __name__ == '__main__':
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten