Mein erstes Projekt^

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Sunny_Shiro1602
User
Beiträge: 2
Registriert: Dienstag 5. Mai 2026, 13:50

Hallo liebe Leute,

um mich optimal auf eine Ausbildung im informatikbereich vorzubreiten habe ich für meine Bewerbung ein kleines Script geschrieben.

ich würde mich gerne darüber freuen wenn jemand mal drüberschaun könnte und mir auch ein schönes feedback und vielleicht auch stellen markiert.

ich habe das alles selbst geschrieben und hatte nur kleine Hilfestellungen von einer KI. Ich selbst war vorher Friseur und will nun eine neuorientierung im Bereich Informatik.


vielen lieben Dank

Eure Sunny


Code: Alles auswählen

import random
import json
import os 


points = 0
difficulty = 1
inventory = []
name = None

def remove_game():
    if os.path.exists("savegame.json"):
        os.remove("savegame.json")
        print("Spielstand gelöscht!")
    else:
        print("Kein Spielstand vorhanden.")

def save_game():
    global name, points, difficulty, inventory

    data = {
        "name": name,
        "points": points,
        "difficulty": difficulty,
        "inventory": inventory
    }

    with open("savegame.json", "w") as file:
        json.dump(data, file)

    print("Spiel gespeichert!")

def load_game():
    global name, points, difficulty, inventory

    try:
        with open("savegame.json", "r") as file:
            data = json.load(file)

        name = data["name"]
        points = data["points"]
        difficulty = data["difficulty"]
        inventory = data["inventory"]
        

        print(f"Spiel geladen! Willkommen zurück, {name}")

    except FileNotFoundError:
        print("Kein Savegame gefunden.")


while True:
    print("\n==== Menü ====")
    print("\n1= Start")
    print("2= Schwierigkeitsgrad")
    print("3= Inventar")
    print("4= Punktestand")
    print("5= Spiel laden")
    print("6= Spiel speichern")
    print("7= Spielstand löschen")
    print("8= Beenden")

    number = input("\nWas willst du tun? ")

    match number:
        case "1":

            bonus_damage = 0

            if name is None: 

                name = input("Wie heißt du? ")
                print(f"Spiel startet für {name}") 

            else:
                print(f"Willkommen zurück, {name}")


            if difficulty == 3:
                monster_name = "Drache"
                monster_lifepoints = random.randint(10, 15)

            else:
                monster_name = "Gobblin"
                monster_lifepoints = random.randint(5, 10)

            monster_strength = monster_lifepoints

            print(f"\nEin {monster_name} erscheint. Es hat {monster_lifepoints} Leben!")

            player_lifepoints = 15 - (difficulty * 3)
            print(f"Spieler {name} hat {player_lifepoints} Leben.")

            while monster_lifepoints > 0:

                print("\nWas möchtest du machen?")
                print("1= Angreifen")
                print("2= Ablenken")
                print("3= Fliehen")
                print("4= Inventar")
                print("5= Beenden")

                action = input("\nDeine Wahl: ")

                match action:
                    case "1":

                        attack_points = random.randint(1, 9) + bonus_damage
                        bonus_damage = 0
                        crit_chance = random.randint(1, 10)

                        if crit_chance == 1:
                            attack_points *= 2
                            print("Kritischer Treffer")

                        monster_lifepoints -= attack_points
                        print(f"Du machst {attack_points} Schaden!")

                        if monster_lifepoints <= 0:

                            reward = monster_strength * 1.5 * difficulty 
                            points += reward

                            loot = random.choice(["Heiltrank", "Gold", "Schwertsplitter"])
                            inventory.append(loot)

                            print(f"{monster_name} ist besiegt! Du bekommst {reward} Punkte!")
                            print(f"Du hast {loot} gefunden!")

                            print(f"\nAktueller Punktestand: {points}")
                            break

                        print(f"{monster_name} hat noch {monster_lifepoints} Leben")

                        monster_attack = random.randint(1, 10)
                        player_lifepoints -= monster_attack

                        print(f"{monster_name} greift {name} an und macht {monster_attack} Schaden!")
                        print(f"\n{name} hat noch {player_lifepoints} Leben")

                        if difficulty == 3:
                            crit_chance = random.randint (1, 15)


                        else: 
                            crit_chance = random.randint(1, 5)


                        if player_lifepoints <= 0:
                            print(f"Spieler {name} ist besiegt. Game over")
                            break


                    case "2":

                        if random.randint(1, 2) == 1:
                            print("Ablenkung gelungen")
                            break

                        else:
                            print("Ablenkung fehlgeschlagen")

                    case "3":

                        if random.randint(1, 2) == 1:
                            print("Du bist geflohen ")
                            break

                        else:
                            print(f"Flucht fehlgeschlagen! Das {monster_name} greift dich an!")



                    case "4":
                        
                        print("\nWelches Item willst du benutzen?")
                        print("1= Heiltrank (+5 Leben)")
                        print("2= Schwertsplitter (+5 Schaden)")

                        item_choice = input("\nDeine Wahl: ")

                        if item_choice == "1":

                            if "Heiltrank" in inventory:
                                old_hp = player_lifepoints
                                max_hp = 15 - (difficulty *3)

                                player_lifepoints = min(player_lifepoints + 5, max_hp)

                                inventory.remove("Heiltrank")

                                print(f"Du hast einen Heiltrank benutzt! {old_hp} -> {player_lifepoints} Lebenspunkte")
                                

                            else:
                                print("Du hast keinen Heiltrank!")


                        elif item_choice == "2":

                            if "Schwertsplitter" in inventory:
                                attack_points += 5
                                inventory.remove("Schwertsplitter")
                                print("Schwertsplitter wurde benutzt")

                            else: 
                                print("Du hast keinen Schwertsplitter")

                        else:
                            print("Ungültige Eingabe")


                    case "5":
                        print("Game Over")
                        break

                    case _:
                        print("Ungültige Eingabe")

        case "2":
            print("\n1= leicht")
            print("2= normal")
            print("3= schwer")

            choice = input("\nSchwierigkeitsgrad: ")


            match choice: 
                case "1":
                    difficulty=1

                case "2":
                    difficulty=2

                case "3":
                    difficulty=3

                case _:
                    print("Ungültige Eingabe")

        case "3": 
            
            print("\n====INVENTAR====")
                  
            if len(inventory) == 0:
                print("Inventar ist leer")

            else: 
                for item in inventory:
                    print(f"- {item}")

        
        
        case "4":

            if "name" in globals():
                print(f"\n==== SPIELER {name} STATUS====")
            
                print(f"Aktueller Punktestand: {points}")
                print(f"Schwierigkeitsgrad: {difficulty}")

                print("--------------------------\n")

            else: 
                print("\n==== SPIELER STATUS====")
                print(f"Aktueller Punktestand: {points}")
                print(f"Schwierigkeitsgrad: {difficulty}")

                print("--------------------------\n")


        case "5":
            load_game()

        case "6":
            save_game()


        case "7":
            remove_game()


        case "8":
            print("Spiel wird beendet...")
            break

        case _:
            print("Ungültige Eingabe")


Benutzeravatar
__blackjack__
User
Beiträge: 14395
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sunny_Shiro1602: Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Keine Variablen, und das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

``global`` hat in einem sauberen Programm nichts zu suchen. Funktionen bekommen alles was sie ausser Konstanten benötigen als Argument(e) übergeben. Wenn eine Funktion ein Ergebnis hat, dann gibt man das an den Aufrufer zurück und verändert nicht globale Variablen.

Der Dateiname der Spielstanddatei steht dreimal im Quelltext. Solche Wiederholungen von Daten sind fehleranfällig. Man kann sich beim ersten schreiben schon vertippen. Oder wenn man den Namen mal ändern will kann man sich wieder vertippen, oder nicht alle Kopien ändern. Für so etwas definiert man eine Konstante. Schönes Beispiel ist "Schwertsplitter". Da ist ein zusätzlichen Zeichen an einer Stelle, so dass die nicht aus dem Inventar entfernt werden.

Man sollte auch keinen Code wiederholen. Die Spielerlebenspunkte und `max_hp` werden nach der gleichen Formel berechnet, die zweimal im Code steht. `max_hp` ändert sich auch nicht während des Spiels, also ändert sich `max_hp` auch nicht, braucht also nur einmal berechnet werden. `lifepoints` an der Stelle mit `hp` abzukürzen ist unerwartet.

Die Funktionen im `os.path()`-Modul sind fast alle durch das `pathlib`-Modul ersetzt.

Beim öffnen von Textdateien sollte man immer die Kodierung mit angeben. Für JSON muss das UTF-8 sein.

Man sollte nicht selbst auf die Existenz einer Datei prüfen und dann etwas damit machen. Zwischen dem was man machen will und dem prüfen kann die Datei gelöscht werden, das heisst man muss sowieso auf eine entsprechende Ausnahme reagieren. In `load_game()` wird das ja beispielsweise auch so gemacht.

In die Funktionen die mit der Spielstanddatei arbeiten würde ich keine Benutzerinteraktion stecken.

`number` ist kein so glücklicher Name für eine Zeichenkette. Und man muss nicht für jede Eingabe vom Benutzer einen neuen Variablennamen erfinden, wenn die Verwendungen sich gar nicht überschneiden.

``match``/``case`` ist hier mit Kanonen auf Spatzen geschossen. Wenn nicht in mindestens einem ``case`` ein Name zugewiesen wird, ist das in der Regel das falsche Werkzeug. Das ist einfach jeweils ein ``if``/``elif``/``else``-Konstrukt. Spart damit auch zwei Einrückebenen.

Das Hauptprogramm ist zu lang, zu tief verschachtelt, und zu unübersichtlich. Das sollte man auf Funktionen aufteilen.

`bonus_damage` macht keinen Sinn. Das hat immer den Wert 0. `attack_points` kann undefiniert sein, wenn man den Schwertsplitter benutzt, weil das nur definiert wird, wenn man angreift. Und den Schwertsplitter benutzen hat gar keinen Effekt, weil `attack_points` zwar um 5 erhöht wird, beim Angriff wird der Wert aber komplett neu ausgewürfelt, bevor er verwendet wird.

Die Stelle wo `crit_chance` anhand der `difficulty` unterschiedlich ausgewürfelt wird, macht keinen Sinn, weil der dort ermittelte `crit_chance`-Wert nirgends verwendet wird.

Beim festlegen des Schwierigkeitsgrads entspricht die Zeichenkette immer der Zahl → da könnte man einfach die Zeichenkette in die Zahl umwandeln.

``if "name" in globals()`` ist immer wahr in dem Code, der ``else``-Zweig kann also nie genommen werden. Beide Zweige enden mit den gleichen drei Codezeilen, die sollten also nur _einmal_ und _nach_ dem ``if``/``else`` stehen.

Das Inventar ist als Liste nicht so elegant. Das wäre eigentlich ein Wörterbuch das Gegenstände auf die Anzahl abbildet, die man davon hat.

Wenn man das auf Funktionen aufteilt werden für meinen Geschmack schon zu viele einzelne Werte hin und her gereicht — da sollte man mit Klassen anfangen sinnvoll zusammenzufassen.
“It is well known that a vital ingredient of success is not knowing that what you're attempting can't be done.”
— Terry Pratchett, Equal Rites
Benutzeravatar
kbr
User
Beiträge: 1511
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Sunny_Shiro1602: die von __blackjack__ angemerkten Code-Duplizierungen sind ein typisches Zeichen von KI-Unterstützung. Das "match/case" Konstrukt ist in Python deutlich mächtiger als in manchen andere Sprachen, da es ein type-pattern-matching darstellt. Daher auch die Empfehlung im konkreten Fall lieber elif-Kaskaden zu nutzen.

Ansonsten ist dein Einsatz zu loben und du solltest dich nicht von konstruktiver Kritik abschrecken lassen, sondern diese nutzen.

Vibe-Coding klappt aktuell nur auf Senior-Level, da die Ergebnisse beurteilt werden müssen. Dies zu wissen ist womöglich auch wertvoll für das was du vor hast.
Benutzeravatar
__blackjack__
User
Beiträge: 14395
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sunny_Shiro1602: Das mit dem Tippfehler beim Schwertsplitter war mein Fehler, sorry. Aber Grundsätzlich kann das ein Problem sein, literale Werte so oft zu wiederholen.

Ich habe mir den Spielablauf noch mal angeschaut und folgende Probleme/Fehler gefunden:
  1. Wenn man besiegt wurde, kann man einfach weitermachen als wäre man gar nicht gestorben.
  2. Ablenken und Fliehen machen genau das gleiche, nur mit anderen Ausgabetexten. Und man kann auch einfach Beenden wählen: warum gibt es dann Ablenken und Fliehen überhaupt?
  3. Die Angriffsstärke vom Monster ist bei allen Monstern gleich. Hat ein Drache tatsächlich keine höhere Schlagkraft als ein Gobblin?
  4. Wozu gibt es Gold? Das hat in dem Spiel keine wirkliche Funktion.
Das ist so ein typisches Programm, mit dem man damals, als ich angefangen habe zu programmieren, auch angefangen hätte. In BASIC auf einem 8-Bit Rechner. :-)
“It is well known that a vital ingredient of success is not knowing that what you're attempting can't be done.”
— Terry Pratchett, Equal Rites
Sunny_Shiro1602
User
Beiträge: 2
Registriert: Dienstag 5. Mai 2026, 13:50

__blackjack__ hat geschrieben: Donnerstag 7. Mai 2026, 16:21 @Sunny_Shiro1602: Das mit dem Tippfehler beim Schwertsplitter war mein Fehler, sorry. Aber Grundsätzlich kann das ein Problem sein, literale Werte so oft zu wiederholen.

Ich habe mir den Spielablauf noch mal angeschaut und folgende Probleme/Fehler gefunden:
  1. Wenn man besiegt wurde, kann man einfach weitermachen als wäre man gar nicht gestorben.
  2. Ablenken und Fliehen machen genau das gleiche, nur mit anderen Ausgabetexten. Und man kann auch einfach Beenden wählen: warum gibt es dann Ablenken und Fliehen überhaupt?
  3. Die Angriffsstärke vom Monster ist bei allen Monstern gleich. Hat ein Drache tatsächlich keine höhere Schlagkraft als ein Gobblin?
  4. Wozu gibt es Gold? Das hat in dem Spiel keine wirkliche Funktion.
Das ist so ein typisches Programm, mit dem man damals, als ich angefangen habe zu programmieren, auch angefangen hätte. In BASIC auf einem 8-Bit Rechner. :-)
Ich habe das spiel komplett neu verbessert ukd tatsächlich auch geschafft auf mein github zu laden. Ich habe auch viele kleine bugs behoben

Code: Alles auswählen

import random
import json
import os

points = 0
difficulty = 1
inventory = []
name = None
gold = 0
level = 1
xp = 0
current_area = None  # NEU: Trackt aktuelles Gebiet

level_thresholds = {
    1: 0,
    2: 100,
    3: 250,
    4: 450,
    5: 700,
    6: 1000,
    7: 1400,
    8: 1900,
    9: 2500,
    10: 3200
}

monsters = {
    # DUNKLER WALD (Level 1-3)
    "Schleim": {
        "lifepoints": (5, 10),
        "damage": (1, 5),
        "lore": "Ein blauer Schleim kommt und versperrt dir den Weg. \nEr sieht aus als hätte er einen schlechten Tag."
    },
    "Goblin": {
        "lifepoints": (10, 15),
        "damage": (5, 10),
        "lore": "Ein Goblin springt aus dem Gebüsch!\nEr riecht nach alten Socken."
    },

    # VERFLUCHTE BERGE (Level 4-6)
    "Fledermaus": {
        "lifepoints": (15, 20),
        "damage": (10, 15),
        "lore": "Eine flattrige Fledermaus greift dich an.\nSie will wahrscheinlich dein Blut."
    },
    "Wolf": {
        "lifepoints": (15, 20),
        "damage": (8, 14),
        "lore": "Ein grauer Wolf knurrt dich an.\nSeine Augen leuchten im Dunkeln."
    },

    # WUESTE DER VERLORENEN (Level 7-9)
    "Skorpion": {
        "lifepoints": (20, 25),
        "damage": (12, 18),
        "lore": "Ein riesiger Skorpion kriecht aus dem Sand.\nSein Stachel tropft vor Gift."
    },
    "Drache": {
        "lifepoints": (20, 25),
        "damage": (15, 20),
        "lore": "Ein Drache bewacht den Eingang. Er ist müde und hat eigentlich keinen Bock!"
    },

    # GRUSELIGER FRIEDHOF (Level 5 - Einmalig)
    "Geist": {
        "lifepoints": (18, 22),
        "damage": (12, 18),
        "lore": "Ein blasser Geist schwebt durch die Grabsteine.\nEr murmelt unverständliche Worte..."
    },
    "Skelett": {
        "lifepoints": (15, 20),
        "damage": (10, 16),
        "lore": "Ein klapperndes Skelett erhebt sich aus dem Grab.\nDie Knochen rasseln bedrohlich."
    },
}


def remove_game():
    if os.path.exists("savegame.json"):
        os.remove("savegame.json")
        print("Spielstand gelöscht!")
    else:
        print("Kein Spielstand vorhanden.")


def save_game():
    global name, points, difficulty, inventory, level, xp, gold
    data = {
        "name": name,
        "points": points,
        "difficulty": difficulty,
        "inventory": inventory,
        "level": level,
        "xp": xp,
        "gold": gold,
    }
    with open("savegame.json", "w") as file:
        json.dump(data, file)
    print("Spiel gespeichert!")


def load_game():
    global name, points, difficulty, inventory, level, xp, gold
    try:
        with open("savegame.json", "r") as file:
            data = json.load(file)
        name = data["name"]
        points = data["points"]
        difficulty = data["difficulty"]
        inventory = data["inventory"]
        level = data["level"]
        xp = data["xp"]
        gold = data["gold"]
        print(f"Spiel geladen! Willkommen zurück, {name}")
    except FileNotFoundError:
        print("Kein Savegame gefunden.")


while True:
    print("\n==== Menü ====")
    print("\n1= Start")
    print("2= Schwierigkeitsgrad")
    print("3= Inventar")
    print("4= Punktestand")
    print("5= Spiel laden")
    print("6= Spiel speichern")
    print("7= Spielstand löschen")
    print("8= Beenden")

    number = input("\nWas willst du tun? ")

    match number:
        case "1":
            bonus_damage = 0
            keep_fighting = True

            if name is None:
                name = input("Wie heißt du? ")
                print(f"""\nIn der Welt von Zylon existieren viele Legenden.
Die meisten davon sind falsch.
Eine davon... vielleicht nicht.

Die Legende der Goldenen Milch.

Man sagt, wer sie trinkt, schnurrt für immer glücklich.
Man sagt, sie liegt verborgen in der Goldenen Zitadelle.

Du, {name}, ein junges Kätzchen aus Sonnenhain, hast
dich entschlossen dass du nun alt genug bist um danach zu suchen.
Voller Stolz hast du einen Beutel genommen und deine Lieblingsmaus,
einen Fisch und etwas Milch eingepackt und bist gegangen.

Sonnenhain liegt hinter dir.
Das große Abenteuer liegt vor dir.
Und irgendwo tief in Zylon warten Gefahren auf dich.

Viel Erfolg, {name}.
Du wirst es brauchen.
""")
            else:
                print(f"Willkommen zurück, {name}")

            while keep_fighting:
                bonus_damage = 0

                if level == 10:
                    print("""
Die Goldene Zitadelle liegt vor dir.
Du öffnest das schwere Tor und...

Ein RIESIGER oranger Kater blockiert den Weg.
Er liegt auf einem goldenen Kissen.
Neben ihm: Die Goldene Milch.

Er hebt langsam den Kopf.
Schaut dich an.
Gelangweilt, so als wärst du es nicht wert diese monströse Flauschigkeit anzusehen.

"Pathetic."
                    """)

                    monster_name = "Der Chonk"
                    monster_lifepoints = 100
                    monster_damage_range = (20, 30)
                    monster_strength = monster_lifepoints

                    print(f"\n{monster_name} erhebt sich majestätisch!")
                    print(f"Er hat {monster_lifepoints} Leben!")

                else:
                    # Gebiet basierend auf Level bestimmen
                    if level <= 3:
                        area_name = "Dunkler Wald"
                        if current_area != area_name:
                            print("\n=== Dunkler Wald ===")
                            print(""" Der dunkle Wald ist dafür bekannt das seine Bäume so hoch und dicht wachsen,
das es dort wie immer Nacht wirkt. In dem Wald gibt es kaum fröhliche Geräusche von 
Vögeln oder anderen friedlichen Waldtieren. In diesem Wald leben Schleime und Goblins.
Sei vorsichtig kleines Kätzchen.""")
                            current_area = area_name
                        available_monsters = ["Schleim", "Goblin"]

                    elif level == 4 or level == 6:
                        area_name = "Verfluchte Berge"
                        if current_area != area_name:
                            print("\n=== Verfluchten Berge ===")
                            print(""" Dein Weg führt dich weiter durch die verfluchten Bergen. Aber warum trägt er diesen Namen?
Tief in der Berglandschaft versteckt liegt der gruselige Friedhof. Niemand traut sich mehr dorthin
und so konnten Fledermäuse und Wölfe sich frei vermehren und greifen jeden an der sich ihrem Gebiet nähert.""")
                            current_area = area_name
                        available_monsters = ["Fledermaus", "Wolf"]

                    elif level == 5:
                        area_name = "Gruseliger Friedhof"
                        if current_area != area_name:
                            print("\n=== Der gruseligen Friedhof ===")
                            print(""" Du hast die Mitte der Berge erreicht und vor dir liegt der Friedhof. Eine alte Hexe hat ihn damals verflucht,
Seitdem leben dort verlorene Seelen als Geister und erschrecken jeden der es wagt diesen Friedhof zu überqueren.
Manchmal erscheinen auch Skelette die auf der suche nach neuen Knochen die Reisenden angreifen.""")
                            current_area = area_name
                        available_monsters = ["Geist", "Skelett"]

                    elif 7 <= level <= 9:
                        area_name = "Wüste der Verlorenen"
                        if current_area != area_name:
                            print("\n=== die Wüste der Verlorenen ===")
                            print(""" Du bist nun kurz vor deinem Ziel. Vor dir erstreckt sich die Wüste der Verlorenen. Viele sind in der sengenden 
Hitze verloren gegangen und gestorben. Doch du, kleiner Held, scheinst mutig genug zu sein und 
wagst dich durch die Wüste. Hier werden dir Skorpione und Drachen begegnen. Achte auf deine
Lieblingsmaus und deine Milch. Bald bist du dem Ziel nahe.""")
                            current_area = area_name
                        available_monsters = ["Skorpion", "Drache"]

                    else:
                        # Fallback
                        available_monsters = ["Schleim", "Goblin"]

                    # Monster spawnen
                    monster_name = random.choice(available_monsters)
                    lp_min, lp_max = monsters[monster_name]["lifepoints"]

                    if monster_name != "Schleim":
                        lp_min += (level * 2)
                        lp_max += (level * 2)

                    monster_lifepoints = random.randint(lp_min, lp_max)

                    damage_min, damage_max = monsters[monster_name]["damage"]

                    if monster_name != "Schleim":
                        damage_min += level
                        damage_max += level

                    monster_damage_range = (damage_min, damage_max)
                    monster_strength = monster_lifepoints

                    print(monsters[monster_name]["lore"])
                    print(f"{monster_name} hat {monster_lifepoints} Leben!")

                player_lifepoints = 30 + (level * 5) - (difficulty * 3)
                print(f"{name} hat {player_lifepoints} Leben.")

                while monster_lifepoints > 0:
                    print("\nWas möchtest du machen?")
                    print("1= Angreifen")
                    print("2= Fliehen")
                    print("3= Inventar")
                    print("4= Beenden")

                    action = input("\nDeine Wahl: ")

                    match action:
                        case "1":
                            attack_points = random.randint(1 + level, 9 + level) + bonus_damage

                            if difficulty == 1:
                                crit_chance = random.randint(1, 5)
                            elif difficulty == 2:
                                crit_chance = random.randint(1, 10)
                            else:
                                crit_chance = random.randint(1, 15)

                            if crit_chance == 1:
                                attack_points *= 2
                                print("Kritischer Treffer!!")

                            bonus_damage = 0

                            if random.randint(1, 5) == 1:
                                print(f"{monster_name} weicht aus!")
                            else:
                                monster_lifepoints -= attack_points
                                print(f"Du machst {attack_points} Schaden!")

                                if monster_lifepoints <= 0:
                                    # BOSS BESIEGT = SPIEL GEWONNEN!
                                    if monster_name == "Der Chonk":
                                        print(f"""
{monster_name} seufzt und legt sich wieder hin.

"Du hast gewonnen... *gähn*
 Nimm die Milch und verschwinde.
 Ich will schlafen."

Du nimmst die Goldene Milch.
Sie funkelt in deinen Pfoten.
Du nippst daran...

...

{name} schnurrt.
Für immer glücklich.

ZYLON IST GERETTET!
Du hast das Spiel gewonnen!
                                        """)
                                        keep_fighting = False
                                        break

                                    # Normale Monster besiegt
                                    reward = monster_strength * 1.5 * difficulty
                                    points += reward
                                    xp += int(reward)
                                    print(f"Du bekommst {int(reward)} XP!")

                                    if level < 10 and xp >= level_thresholds[level + 1]:
                                        level += 1
                                        print(f"""
LEVEL UP! Du bist jetzt Level {level}!
{name} schnurrt stolz vor sich hin!
""")
                                        if level < 10:
                                            next_level_xp = level_thresholds[level + 1]
                                            xp_needed = next_level_xp - xp
                                            print(f"Bis Level {level + 1}: noch {xp_needed} XP")
                                        else:
                                            print("MAX LEVEL erreicht! Die Goldene Zitadelle wartet!")

                                    loot = random.choice(["Heiltrank", "Schwertsplitter"])
                                    inventory.append(loot)

                                    new_gold = random.randint(1, 10)
                                    gold += new_gold

                                    print(f"{monster_name} ist besiegt! Du bekommst {reward} Punkte!")
                                    print(f"Du hast {loot} gefunden!")
                                    print(f"Du hast {new_gold} Gold gefunden! (Gesamt: {gold})")
                                    print(f"\nAktueller Punktestand: {points}")
                                    print("\nWas möchtest du tun?")
                                    print("1= Weiter kämpfen")
                                    print("2= Shop besuchen")
                                    print("3= Zurück zum Menü")

                                    after_fight = input("\nDeine Wahl: ")
                                    match after_fight:
                                        case "1":
                                            break
                                        case "2":
                                            print("\n==== SHOP =====")
                                            print("\nHerzlich Willkommen beim fahrendem Händler")
                                            print(f"\nDein Gold: {gold}")
                                            print("==========================")
                                            print("1= Heiltrank (7 Gold)")
                                            print("2= Schwertsplitter (5 Gold)")
                                            buy = input("\nDeine Wahl: ")
                                            match buy:
                                                case "1":
                                                    if gold >= 7:
                                                        gold -= 7
                                                        inventory.append("Heiltrank")
                                                        print("Heiltrank gekauft!")
                                                    else:
                                                        print("Nicht genügend Gold")
                                                case "2":
                                                    if gold >= 5:
                                                        gold -= 5
                                                        inventory.append("Schwertsplitter")
                                                        print("Schwertsplitter gekauft!")
                                                    else:
                                                        print("Nicht genügend Gold.")
                                                case _:
                                                    print("Ungültige Eingabe")
                                            break
                                        case "3":
                                            keep_fighting = False
                                            break

                                print(f"{monster_name} hat noch {monster_lifepoints} Leben")
                                damage_min, damage_max = monster_damage_range
                                monster_attack = random.randint(damage_min, damage_max)
                                player_lifepoints -= monster_attack
                                print(f"{monster_name} greift {name} an und macht {monster_attack} Schaden!")
                                print(f"\n{name} hat noch {player_lifepoints} Leben")
                                if player_lifepoints <= 0:
                                    print(f"{name} ist besiegt. Game over!")
                                    keep_fighting = False
                                    break

                        case "2":
                            if random.randint(1, 2) == 1:
                                print("Du bist geflohen!")
                                break
                            else:
                                print(f"Flucht fehlgeschlagen! Das {monster_name} greift dich an!")
                                damage_min, damage_max = monster_damage_range
                                monster_attack = random.randint(damage_min, damage_max)
                                player_lifepoints -= monster_attack
                                print(f"{monster_name} macht {monster_attack} Schaden!")
                                print(f"Du hast noch {player_lifepoints} Leben!")
                                if player_lifepoints <= 0:
                                    print(f"{name} ist besiegt. Game over!")
                                    keep_fighting = False
                                    break

                        case "3":
                            print("\nWelches Item willst du benutzen?")
                            options = {}
                            if "Heiltrank" in inventory:
                                print("1= Heiltrank (5+ Leben)")
                                options["1"] = "Heiltrank"
                            if "Schwertsplitter" in inventory:
                                print("2= Schwertsplitter (+5 Schaden)")
                                options["2"] = "Schwertsplitter"
                            if not options:
                                print("Du hast keine Items!")
                                continue
                            item_choice = input("\nDeine Wahl: ")
                            if item_choice in options:
                                item = options[item_choice]
                                if item == "Heiltrank":
                                    old_hp = player_lifepoints
                                    max_hp = 30 + (level * 5) - (difficulty * 3)
                                    player_lifepoints = min(player_lifepoints + 5, max_hp)
                                    inventory.remove("Heiltrank")
                                    print(f"Heiltrank benutzt! {old_hp} -> {player_lifepoints} Leben")
                                elif item == "Schwertsplitter":
                                    bonus_damage += 5
                                    inventory.remove("Schwertsplitter")
                                    print("Schwertsplitter benutzt!")
                            else:
                                print("Ungültige Eingabe")

                        case "4":
                            print("Game Over")
                            keep_fighting = False
                            break

                        case _:
                            print("Ungültige Eingabe")

        case "2":
            print("\n1= leicht")
            print("2= normal")
            print("3= schwer")
            choice = input("\nSchwierigkeitsgrad: ")
            match choice:
                case "1":
                    difficulty = 1
                case "2":
                    difficulty = 2
                case "3":
                    difficulty = 3
                case _:
                    print("Ungültige Eingabe")

        case "3":
            print("\n====INVENTAR====")
            if len(inventory) == 0:
                print("Inventar ist leer")
            else:
                for item in inventory:
                    print(f"- {item}")

        case "4":
            if name is not None:
                print(f"\n==== SPIELER {name} STATUS====")
            else:
                print("\n==== SPIELER STATUS====")
            print(f"Aktueller Punktestand: {points}")
            print(f"Schwierigkeitsgrad: {difficulty}")
            print(f"Vermögen: {gold} Gold")
            print(f"Level: {level}")
            print(f"XP: {xp} XP")

            if level < 10:
                next_level_xp = level_thresholds[level + 1]
                xp_needed = next_level_xp - xp
                print(f"Bis Level {level + 1}: noch {xp_needed} XP")
            else:
                print("MAX LEVEL erreicht! Die Goldene Zitadelle wartet!")
            print("--------------------------\n")

        case "5":
            load_game()

        case "6":
            save_game()

        case "7":
            remove_game()

        case "8":
            print("Spiel wird beendet...")
            break

        case _:
            print("Ungültige Eingabe")

Benutzeravatar
__blackjack__
User
Beiträge: 14395
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sunny_Shiro1602: Das Hauptprogramm besteht aus 253 Anweisungen, 75 Verzweigungen, zu tiefer Verschachtelung, und 39 Variablen in 399 Zeilen Code. Jeder dieser Werte ist deutlich zu hoch. Dazu kommen dann noch mehrzeilige Zeichenketten die es noch schwerer machen die Struktur von diesem riesigen Codemonster zu erfassen. Das muss wirklich dringend auf verständliche Funktionen aufgeteilt werden. Und zwar echte Funktionen, also kein ``global``.

Es würde auch Sinn machen noch mehr in Datenstrukturen zu stecken um den Code zu vereinfachen. Also zum Beispiel die Szenen und Level nicht durch Kommentare in der `monsters`-Datenstruktur und durch Code repräsentieren, sondern dafür auch eine Datenstruktur erstellen. Und dann eine für Level wo nicht nur der Schwellwert für das Level hinterlegt ist, sondern auch die jeweilige Szene in der das stattfindet.

An der Stelle könnte man auch überlegen diese Datenstruktur in eine Datendatei auszulagern. JSON ist ja schon bekannt. Aber YAML wäre da auch eine Überlegung Wert, weil man dort zum Beispiel mehrzeilige Texte besser lesbar schreiben kann. Und IDs und Referenzen können hier auch sinnvoll sein, um zum Beispiel bei Monstern die Indirektion über den Namen zu vermeiden.

Ausser beim Schleim spielen "lifepoints" und "damage" aus der `monsters`-Datenstruktur keine Rolle. Das ist ziemlich sicher falsch.

Strukturierung der Daten als Klassen hatte ich ja schon mal angemerkt — das wird jetzt drängender wo wir Wörterbücher (`dict`) haben, die einen gemeinsamen Satz an festen Zeichenketten als Schlüssel haben. Da werden Wörterbücher als spezifischere Datenobjekte missbraucht. Ich sehe da mindestens mal `Monster`, `Scene`, und `Level`, und natürlich `GameState` als mögliche sinnvolle Klassen.
“It is well known that a vital ingredient of success is not knowing that what you're attempting can't be done.”
— Terry Pratchett, Equal Rites
nezzcarth
User
Beiträge: 1805
Registriert: Samstag 16. April 2011, 12:47

Sunny_Shiro1602 hat geschrieben: Dienstag 5. Mai 2026, 13:54 um mich optimal auf eine Ausbildung im informatikbereich vorzubreiten habe ich für meine Bewerbung ein kleines Script geschrieben.
Ich finde deinen Ansatz gut und auch die Idee für das Spiel nett. Als grundsätzliches Feedback kann man aber vielleicht schon mal mitgeben, dass man beim Programmieren im allgemeinen versucht, Abstraktionen und Generalisierungen zu finden, die den Code kürzer und gleichzeitig besser wartbar zu machen. Wenn ein Block wie z.B. deine Game-Loop sehr lang ist, ist das ein starkes Zeichen dafür, dass man hier stärker gliedern müsste. Zudem versucht man möglichst, die Logik von den Daten zu trennen. Beides ist bei dir sehr stark verschachtelt und "zu Fuß" gelöst, was zu schwer les- und wartbarem Code führt, der tief verschachtelt ist. Beispielsweise ist dein Menüsystem über den Code verstreut und ich habe Mühe, zum Beispiel herauszufinden, wo genau die Logik für den Kampf ist etc. Dies alles würde man, wie die anderen schon angemerkt haben, eher durch eine Gliederung in Funktion und die Wahl geeigneter Datenstrukturen lösen. Andererseits ist es aber ja auch so, dass du die Informatik-Ausbildung erst noch machen willst; insofern muss man da sicher auch fair bleiben, was die Anforderungen angeht. Diese Dinge wirst du sicher auch sonst in der Ausbildung noch lernen. :)
Antworten