[Erledigt] Zu bestimmter Stelle zurückkehren

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Hallo zusammen,

    ich habe mittlerweile angefangen ein Tycoon in Python zu programmieren. Dabei tat sich die Frage auf, wie ich an eine bestimmte Stelle im Programm zurückkehren kann :helpnew: .

    Hier wäre der ganze Code:

    Kann mir da vielleicht jemand von euch behilflich sein??

    Danke schonmal für Hilfe :danke_ATDE:

    Gruß

    Kaptain

    Wie heißt eine Schlange, die exakt 3,14 Meter lang ist?

    πthon

  • Hallo Kaptain,

    Zitat


    Nein, Python unterstützt keine Labels und goto, wenn Sie danach suchen. Es ist eine (stark) strukturierte Programmiersprache.

    [Quelle: Goto in Python?]

    Das wird Dir in allen modernen Programmiersprachen so ergehen. Unter "modern" würde ich mal alle Programmiersprachen verstehen, die ab Mitte der 1970er Jahre kreiert wurden.

    Programmiersprachen, die das, was Du vorhast, unterstützen, sind z.B. BASIC.

    Gewöhne Dir das mit Goto oder Label gar nicht erst an. Das ist ganz schlechter Programmierstil und Du versaust Dir jegliches algorithmische und prozedurale Denken. Für den objektorienterten Ansatz ist das auch untauglich.


    Für Dein Vorhaben wirst Du also das Übliche machen müssen:

    • Hauptereignisschleife erkennt Ereignisse
    • Hauptereignisschleife ruft ereignisbasiert Callback-Funktionen auf
    • In den Callback-Funktionen ist das programmiert, was Du machen möchtest
    • Wenn die Callback-Funktion abgearbeitet ist, dann befindet sich das Programm wieder in der Hauptereignisschleife - und das Spiel beginnt von vorne

    Du musst Dein Vorhaben so durchdenken müssen, dass Du keinen Sprung mehr in eine oder mehrere Programmzeilen benötigst.

    Solange Dein Durchdenken der Ablauflogik noch an solchen Sprüngen festhält, bist du von der wahren Lösungen (im Sinne prozeduralen Denkens) noch weit entfernt.

    Oder die Programmiersprache ist für Dich noch ungeeignet. ### Duck und weg ###


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (2. Dezember 2022 um 21:41)

  • Hallo,

    zusätzlich zu der vorherigen Antwort noch ein paar Anmerkungen zu deinem Code.

    Kommentare sollen dem Leser einen Mehrwert bieten. Wenn da steht '# Importe' und darunter folgt eine Zeile mit 'import time', dann ist der Kommentar überflüssig. Noch ungeschickter ist es, wenn der Kommentar eine Liste verspricht und zwei Zeilen später ein Dictonary erzeugt wird. Zusammengefasst, Kommentare sollen nicht beschreiben was der Code macht, sondern warum er etwas macht. Das aber auch nur, wenn es nicht offensichtlich ist.

    Auf Modulebene (der Code ohne Einrückungen) darf zum einen kein ausführbarer Code stehen und zum anderen nichts variables. Hier werden nur Konstanten, Klassen und Funktionen definiert. Die einzige ausführbare Codezeile auf Modulebene ist der Einstiegspunkt in die 'main'-Funktion.

    Verwende sprechende Namen und verwende keine Datentypen in den Namen, das wird echt nervig, wenn man den Datentyp während des Programms mal ändern muss.

    Alle Namen werden klein_mit_unterstrich geschrieben, Ausnahmen sind Konstanten KOMPLETT_GROSS und Klassen in CamleCase-Schreibweise. Funktionen werden nach ihrer Tätigkeit benannt und Dictonary meist nach dem Schema key_to_value.

    Man belegt keine Namen vor, die man irgendwann mal braucht, sondern definiert sie dann, wenn man sie braucht.

    Drei ' sind zur Definition von Doc-Strings vorgesehen.

    Wenn du Strings schreibst und darin Werte verwenden willst, die an einen Namen gebunden sind, dann bieten sich 'f'-Strings an.

    Das Programm wird üblicherweise aus einer Funktion mit dem Namen 'main' gesteuert. Hier gehört auch deine Schleife rein. Darin werden dann Funktionen aufgerufen, Argumente übergeben und Rückgaben entgegen genommen.

    Wahrheitswerte fragt man nicht mit 1 oder 0 ab, sondern nimmt direkt True oder False.

    'clear' macht meiner Meinung nach nicht viel Sinn, es werden 10 Absätze gemacht, wenn das Fenster aber groß genug ist, dann sieht man immer noch vorherige Ausgaben.

    Anstelle der Input-Abfrage nach None würde ich dafür sorgen, dass falsche Eingaben wie '5', 'xy' oder ähnliches abgefangen werden.

    In 'buy' ziehst du den Preis von deinem Guthaben ab, aber das Ergebnis bindest du an keinen namen und macht nichts damit.

    'upgrade' macht nichts und das bei 'show' ein Error kommt ist auch nicht zu erwarten.

    Wenn du so lange die Eingabe kontrolieren willst, bis du mit dem Ergebnis zufrieden bist, dann kannst du das in eine Funktion auslagern und gleichzeitig kannst du diese Funktion aber auch in einer Schleife aufrufen. Schau dir mal folgendes Beispiel an. An Stelle von 'print(user_input)' kannst du ja etwas mit dem 'user_input' machen, z.B. deine Vergleiche abfragen.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Andreas OK, dann mach das ganze halt so, dass alles in der Schleife liegt.

    Dennis89 Deinen Code verstehe ich leider eher nicht, was wahrscheinlich daran liegt, dass ich noch Anfänger bin. Über eine „Erklärung“ würde ich mich freuen, ansonsten mache ich das ganze einfach anders. Dass dort print(‚Error‘) steht, liegt daran, dass ich diese Definition einfach noch nicht fertig programmiert habe und nicht wollte, dass ich erstmal in Error Meldungen ersticke sobald ich das Programm testweise starte. Die ganzen Kommentare dienen mir einfach nur zur Übersicht.

    Danke für eure Antworten!

    Gruß

    Kaptain

    Wie heißt eine Schlange, die exakt 3,14 Meter lang ist?

    πthon

  • Moinsen,

    Ich würde hier auf ein Object ( Klasse ) setzen. Damit man auch mehrere Player verwalten kann, zudem nicht außerhalb oder während eines Rundenverlaufs zig Variablen in der Hauptschleife herumquirlen.

    Damit muss man eine Datensatz haben der die Wertsteigerungen ( Auswirkungen auf das Bargeld / Vermögen ) je Runde als Faktor beinhaltet, und innerhalb des Spieler-Objektes eine weitere Eingabemöglichkeit schafft, das der Spieler seine Züge pro Spielrunde beendet hat.
    In der Hauptschleife muss man dieses UPDATE was aber zu dem jeweiligen Spielerobjekt gehört nur aufrufen, dass alle rundenbasierten Ergebnisse neu berechnet werden. Das heißt, je nach deinem Spielkonzept, Minus Löhne und Gehälter der Manager der Wertschöpfungsquellen ( Fabriken ), den wirtschaftlichen Zugewinn pro Fabrik usw.

    Franky

  • Hallo Kaptain,

    kannst du sagen was genau du nicht verstehst? Wo soll ich ansetzen?

    Den Vorschlag mit der Klasse kannst du erst mal bei Seite legen. Du musst als erstes zwingend mit Funktionen umgehen können.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Hallo Kaptain,

    Du brauchst in erster Linie erst einmal ein Spielkonzeppt !
    Das heißt, was soll und darf in einer Runde alles passieren, dh. auch wieviele Einzelzüge / Schritte pro Runde zulässig sein sollen. Und dann kannst du dir Gedanken über eine strukturierte Ausführung, oder eine OOP Ausführung machen. Wobei Dennis89 schon grundlegend eine Aussage getroffen hat, dass man erst mal die Grundfunktionen beherrschen sollte, und dann sich mit der OOP beschäftigen sollte.
    Für die Erstellung eines Text Adventures findest du im Netz auch sehr viele schöne kleine Beispiele als Lernkurs, an denen du dich erst einmal orientieren kannst.

    Franky

  • Hallo,

    Die ganzen Kommentare dienen mir einfach nur zur Übersicht.

    Ja, aber die Kommentare sind in Teilen falsch. Unter `#listen` legst du eine Liste und ein Dictionary an. Und warum ist die Liste `companies_list` mit einem leeren String vorbelegt?

    Wenn du ein Programm mit einer textbasieren Benutzeroberfläche bauen möchtest, dann kannst du dafür das cmd nehmen, was Python an Bord hat. Ob das zum einzigen Zeitpunkt für dich wirklich zielführend ist... ich würde an deiner Stelle erst nochmal an den Grundlagen der Sprachen feilen.

    Ich würde hier auf ein Object ( Klasse ) setzen.

    Und Python ist alles ein Objekt...

    Gruß, noisefloor

  • Moinsen,

    Und Python ist alles ein Objekt...

    Deswegen stellt der Programmcode des TO #1 eine strukturiertes Programmiermodell dar! Und verwendet keine OOP für die Spielerfunktionen selber.

    Aber du kannst hier gerne weitere dem TO nicht helfende Beiträge verfassen, und bis ins Detail der Interpretation bzw der binären Abarbeitung des interpretierten Pythoncodes = Assembler Code in der CPU eingehen.
    Nur wird das dem TO nicht helfen.

    Franky

  • KaptainAhoibrause Da es glaube ich noch niemand erwähnt hatte: In der Python-Dokumentation gibt es ein Grundlagentutorial das man mal durchgearbeitet haben sollte.

    f-Zeichenkettenliterale wurden schon erwähnt, aber die `format()`-Methode auf Zeichenketten glaube ich noch nicht. Denn die würde man dem ``%``-Operator vorziehen. Das hat man im Grunde in Python 2 schon gemacht.

    Auch noch eine wichtige Sache beim Programmieren: Redundanz bei Daten und Code vermeiden. Wenn man Daten oder Code mehrfach schreibt, erhöht sich die Gefahr das man Fehler macht. Entweder schon beim ersten mehrfachen Schreiben, oder später wenn man etwas am Programm ändert. Dann muss man a) daran denken *alle* Kopien zu ändern und b) das auch bei allen Kopien gleich(wertig) tun. Im PyTycoon betrifft das beispielsweise die Preisliste und den Text vom ``input()``. Der Menütext sollte aus der Preisliste erstellt werden, und nicht von Hand alle Firmentypen und Preise *noch mal* getippt werden.

    Streng genommen gibt es Labels und GOTO in Python — es gibt mindestens zwei Module die man sich installieren kann, die das innerhalb von Funktionen/Methoden ”nachrüsten”. Beides nicht wirklich ernst gemeint, in einem Fall sogar an einem 1. April erschienen aber *funktionierend*! Die eine Lösung arbeitet unter Haube mit Ausnahmen, die andere hackt soweit ich mich erinnere am generierten Bytecode der Funktion rum, denn auf *der* Ebene gibt es Sprünge wie man sie aus Assembler kennt.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Franky07 Das Spiel ist erstmal nur für einen Spieler gedacht und ich wollte eigentlich erst mit der Zeit weitere Funktionen wie z.B.: Multiplayer oder Spielstandspeicherung hinzufügen.

    Dennis89 Ich verstehe in erster Linie def get_user_input usw. nicht. Was genau wird da gemacht?

    noisefloor Die Liste companies_list soll die Firmen beinhalten, die mir gehören. Von Anfang an sind das ja erstmal keine.

    __blackjack__ Mit f-Zeichenkettenliteralen habe ich noch nie gearbeitet, das müsstest du mir also noch mal erklären.

    Noch mal zur Erinnerung: Ich bin absoluter Anfänger und habe mit Python noch allzu viel Programmiert was Taschenrechner undd andere kleine Spielereien übersteigt.

    Danke an alle für die Antworten :danke_ATDE:

    Kaptain

    Wie heißt eine Schlange, die exakt 3,14 Meter lang ist?

    πthon

  • KaptainAhoibrause Die Frage von noisefloor bleibt bestehen: Warum ist da eine leere Zeichenkette in der Liste? Das bedeutet ja Du besitzt *eine* Firma mit einem leeren Namen. Wenn Du am Anfang keine Firmen besitzt, sollte die Liste 0 (Null) Elemente enthalten und nicht 1.

    f-Zeichenkettenliterale muss *ich* Dir nicht erklären, genau so wenig wie Dennis89 Dir Funktionen und deren Definition erklären muss. Dafür gibt es Grundlagentutorials. Vom Status „Absoluter Anfänger“ kommst Du nur so weg. Du wirst selbst Tutorials durcharbeiten müssen. Niemand wird Dir hier die absoluten Grundlagen aus bestehenden Tutorials ”vorlesen” a.k.a. hier häppchenweise ins Forum rüber kopieren, wenn Du sie auch an anderer Stelle im Original lesen kannst.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • framp Ist es IMHO nicht. Klassen sind nun mal *der* Verbunddatentyp in Python und bei so einem Spiel wird man sehr schnell an die Grenze stossen was man sinnvoll an Funktionen übergeben und als Rückgabewert bekommen kann. Selbst wenn man gar nicht objektorientiert programmiert! Das ist als wenn man so ein Spiel in C ohne ``struct`` oder in Pascal ohne RECORD schreiben wollte. Wobei die beiden Sprachen noch den ”Vorteil” haben, dass man (semi)globale Variablen benutzen kann und damit Übersetzungseinheiten quasi als Singleton-Objekte verwendet. Das macht man in Python nicht, und das sollte IMHO auch kein Python-Anfänger so lernen, denn damit würde man ein absolutes No-Go lernen das man dann erst wieder mühsam verlernen muss.

    Was natürlich kontraproduktiv wäre, ist jetzt mit Klassen anzufangen bevor Funktionen sitzen. Also a) das alles was nicht Konstante, Funktion, oder Klasse definiert in einer Funktion steckt, und b) das Funktionen alles was sie ausser Konstanten benötigen als Argument(e) übergeben bekommen und c) Ergebnisse als Rückgabewerte liefern. Das das Konzept von Funktionen noch nicht verstanden wurde, konnte man schon an dem effektlosen ``money - price_list[input_a]`` in der `buy()`-”Funktion” erahnen, und das wurde dann ja bestätigt als bei der Funktionsdefinition die Dennis89 gezeigt KaptainAhoibrause geantwortet hat er versteht das mit den Funktionen nicht. Also muss dieses Verständnisproblem behoben werden *bevor* es an Klassen geht. Das ist aber IMHO nicht ”unsere” Aufgabe hier noch mal Grundlagen zu erklären, also letztlich noch mal Sachen zu schreiben, die in jedem Grundlagentutorial stehen sollten.

    Vielleicht ist ein Handelsspiel auch einfach etwas zu hoch gegriffen für den Anfang und man sollte das noch ein bisschen aufschieben und ein oder zwei einfachere Projekte dazwischen schieben. Ich kann mir so ein Spiel jedenfalls nicht ohne Klassen/``struct``/RECORD/TYPE/… vorstellen. Also eigentlich kann ich mir das doch vorstellen, aber dann wären wir bei den ”klassischen” unstrukturierten BASICs mit Zeilennummern. Ich weiss nicht ob man so etwas Anfängern zumuten möchte, dass es im Grunde nur einen Namensraum gibt; Variablennamen auf maximal zwei Zeichen (nur Grossbuchstaben und Ziffern) beschränkt sind; A, A%, A$, A(), A%(), A$() zwar den gleichen Namen haben, aber alle 6 unterschiedliche Variablen sind, jeweils drei verschiedene Typen und einmal Skalar und einmal Array. Dafür kann man mit GOTO zu bestimmten Stellen zurückkehren. ?

    Da sind wir dann schnell bei so etwas:

    Dazu dann natürlich noch die handgeschriebene Dokumentation was welche Variable bedeutet, die ich mir für diesen Bildschirm voll Code noch gespart habe, die bei einem Spiel dieser Grössenordnung aber wichtig ist/wird.

    Und wo ich das geschrieben habe, fiel mir auf, dass man Firmen offenbar „upgraden“ können soll, also haben gekaufte Firmen individuelle Eigenschaften, wo wir dann schon wieder bei Verbunddatentypen sind, also in Python bei Klassen. Es sei denn man akzeptiert tatsächlich den klassischen BASIC-Weg und fängt an parallele ArraysListen für die Eigenschaften zu führen. Sollte man Anfänger dazu wirklich ermuntern so weit in die falsche Richtung zu laufen, nur weil man ihnen bei einer objektorientierten Programmiersprache keine Klassen zutraut?

    KaptainAhoibrause Es fehlt hier vielleicht auch ein bisschen Planung oder zumindest wird das aus dem bisherigen Quelltext nicht ersichtlich. Was zum Beispiel der „Verdienst pro Sekunde“ am Ende werden soll, oder was `workers` und `manager` bedeuten soll (und ob letzteres nicht tatsächlich `managers` (mehrzahl) heissen sollte). Denn man hat ja Arbeiter/Manager üblicherweise pro Firma und nicht mehrere Firmen und einen Pool an Arbeitern und Managern für alle. Ich würde empfehlen nicht zu viel Dummy-Code zu schreiben der noch gar nichts macht, inklusive Daten die noch gar nicht gebraucht werden. Versuche immer ein funktionierendes Teilergebnis zu haben, das man testen kann, wo alles verwendet wird/werden kann, was bisher da ist. Wenn in dem Programm noch keine Arbeiter oder Manager benutzt werden, sollte man dafür auch keinen ”toten” Code mitschleppen. Das kostet unnötig Zeit beim Schreiben, beim Lesen, bei der Fehlersuche, beim abändern von Code.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • __blackjack__ Ich habe nirgendwo geschrieben das Klassen nicht genutzt werden sollen. Wie Du auch schon schreibst müssen aber erst einmal die Grundlagen "sitzen". Ansonsten kämpft man als Anfänger an zig Fronten und ist irgendwann frustriert. Spätestens wenn Libraries genutzt werden muss man mit Klassen umgehen können. Ich bin aber auch wie Du der Meinung erst einmal mit kleinen Brötchen anzufangen und dann nach und nach die Brötchen wachsen zu lassen :)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!