Alle erstellten Inhalte von Goetz
-
Lua Tutorial
Tabellen - Teil 3 Der Index eines Tabellenelements darf in Lua auch ein String sein. Man kann die Zellen also mit Namen versehen: Farbe = {} Farbe["Rot_Anteil"] = 128 Farbe["Gruen_Anteil"] = 64 Farbe["Blau_Anteil"] = 0 Die Anführungszeichen um den Namen sind erforderlich, damit Lua an dieser Stelle Zellennamen von Variablen unterscheiden kann. In einer vereinfachten Schreibweise hängt man den Index nach einem Punkt an den Tabellennamen. Bei dieser Schreibweise dürfen keine Anführungszeichen verwendet werden. Farbe = {} Farbe.Rot_Anteil = 128 Farbe.Gruen_Anteil = 64 Farbe.Blau_Anteil = 0 Das ist gut lesbar und bequemer zu schreiben. In der Bedeutung ist es mit der ersten Schreibweise identisch. Ebenso kann man namentliche Indexe gleich bei der Initialisierung verwenden: Farbe = {["Rot_Anteil"] = 128, ["Gruen_Anteil"] = 64, ["Blau_Anteil"] = 0} oder in der vereinfachten Schreibweise: Farbe = {Rot_Anteil = 128, Gruen_Anteil = 64, Blau_Anteil = 0} Bitte beachten: Diese vereinfachten Schreibweisen sind ausschließlich für Strings geeignet. Eine Nummer als Zellenindex muss in eckigen Klammern stehen. Ein Variablename ebenfalls. Nummeriete und namentlich bezeichnete Zellen dürfen in derselben Tabelle vorkommen: Band = {"John", "Paul", "George", "Ringo", Name = "Beatles"} print("Die "..Band.Name.." sind: "..Band[1]..", "..Band[2]..", "..Band[3].." und "..Band[4]) Zur Erinnerung: Mit einem # vor dem Tabellennamen bekommt man den Index vor der ersten Lücke im durchnummerierten Teil einer Tabelle. Im vorliegenden Beispiel liefert #Band also den Wert 4. Die Zelle "Name" wird nicht mitgezählt. Die Funktionen table.insert() und table.remove() verlangen als Index eine Nummer. Sie können nicht auf namentlich indizierte Zellen angewendet werden. Möchte man eine Zelle löschen, dann weist man ihr den Wert nil zu. Das funktioniert mit jedem Index. Ist der Index eine Zahl, dann werden die nachfolgenden Zellen nicht verschoben und es entsteht eine Lücke in der Nummerierung.
-
Lua Tutorial
Tabellen - Teil 2 Möchte man wissen, wieviele Elemente sich in einer Tabelle befinden, dann kann man diese Zahl mit einem # vor dem Namen der Tabelle bekommen: Beispiel = {"Eins", "Zwei", "Drei"} Anzahl = #Beispiel Man kann in Lua eine leere Tabelle anlegen Beispiel = {} Und anschließend Elemente hinzufügen Beispiel[1] = "Eins" Beispiel[2] = "Zwei" Bei dieser Methode werden keine Elemente verschoben. Eventuell vorhandene Elemente werden überschrieben. Wenn man den Index angibt, unter dem Elemente gespeichert werden sollen, sind Lücken in der Liste möglich Beispiel[5] = "Fünf" #Beispiel gibt in diesem Fall den Index vor der ersten Lücke zurück. Das wäre im vorliegenden Beispiel eine 2 Im folgenden Beispiel wäre es eine 5, obwohl die Elemente 1 und 2 nicht existieren und das letzte Element den Index 7 hat. Beispiel = {} Beispiel[3] = "Drei" Beispiel[4] = "Vier" Beispiel[5] = "Fünf" Beispiel[7] = "Sieben" print(#Beispiel) Man kann Tabellen wahlweise nutzen um sortierte, durchnummerierte Listen zu erstellen oder um Elemente an bestimmte Nummern wie z.B. IDs zu knüpfen. Da Lua beides im selben Typ 'table' verwaltet, muss man selbst darauf achten, die beiden Fälle richtig zu unterscheiden. Für Änderungen an durchnummerierten Listen gibt es unter anderem die Funktionen table.insert(Tabelle, Index, Wert) und table.remove(Tabelle, Index) Lässt man bei table.insert() den Index weg (zwei Parameter statt drei), hängt es den neuen Wert dort an, wo in der Liste die erste Lücke gefunden wird. Nachfolgende Elemente verschieben sich nicht! Damit fungiert es als append, welches Lua nicht als eigenständige Funktion bietet. Beispiel = {} Beispiel[3] = "Drei" Beispiel[4] = "Vier" Beispiel[5] = "Fünf" Beispiel[9] = "Neun" table.insert(Beispiel, "Sechs") for i = 1, 10 do print(i.." - ", Beispiel[i]) end Die Funktion table.remove() liefert den entfernten Wert als Ergebnis zurück. Beispiel = {"Eins", "Zwei", "Drei", "Vier", "Fünf", "Sechs"} for i = #Beispiel-1, 1, -1 do table.insert(Beispiel, table.remove(Beispiel, i)) end for i = 1, #Beispiel do print(i.." - "..Beispiel[i]) end
-
Lua Tutorial
Tabellen - Teil 1 Variablen bieten die Möglichkeit, einen Wert unter einem Namen abzulegen. Oftmals ist es aber sinnvoll, mehrere Werte unter einem einzelnen Namen zusammenzufassen, weil sie in irgendeiner Weise zusammengehören. Koordinaten zum Beispiel. Oder Farbwerte. Oder Personendaten. Oder alle Parameter einer Lok (Name, Geschwindigkeit, Ort …) Für diesen Zweck bietet Lua Tabellen. Und in Lua gibt es nur Tabellen. Andere Programmiersprachen kennen außerdem Listen, Dictionaries, Tupfes und mehr. Lua fasst das alles in einem Typ 'table' zusammen. Tabellen werden mit geschweiften Klammern erzeugt. Koordinaten = {0, 0, 0} und die Elemente einer Tabelle werden durch ein Komma getrennt. Die geschweiften Klammern findet man auf einer normalen, deutschen PC-Tastatur mit AltGr 7 und AltGr 0 Die einzelnen Elemente einer Tabelle sind indiziert. Das bedeutet, dass sie durchnummeriert sind. Und dass man sie über diese Nummer ansprechen kann. Den Index eines Tabellenelements schreibt man bei Lua in eckige Klammern Koordinaten[1] Die eckigen Klammern findet man auf einer normalen, deutschen PC-Tastatur mit AltGr 8 und AltGr 9 Eine Lua Tabelle darf Elemente unterschiedlichen Typs enthalten Person = {"Max", "Mustermann", 182, 3.5, true} Diese Tabelle enthält zwei Strings, eine Ganzzahl, eine Fließkommazahl und ein Boolean. Das erste Element einer Tabelle hat den Index 1 Person[1] == "Max" Darin unterscheidet sich Lua von allen anderen Programmiersprachen! Für den Einsteiger ist diese Nummerierung sehr angenehm, weil sie seinen Erwartungen entspricht. Für routinierte Programmierer ist sie eine Falle, weil sie den bisherigen Gewohnheiten widerspricht. Für die Lesbarkeit darf man beliebig viele Leerzeichen einfügen. Farbe = {0, 32, 128} und Farbe = { 0, 32, 128} sind identisch. Ebenso darf man Zeilenumbrüche einfügen um die Lesbarkeit zu verbessern Texte = { "Eine Lok steht auf Gleis 1", "Der Güterzug wurde abgefertigt", "Der Weg für den Schnellzug ist frei", "Der Schattenbahnhof ist voll!" } Das Komma als Trennzeichen zwischen den Elementen ist auch bei mehrzeiliger Schreibweise zwingend erforderlich. Hinter dem letzten Element ist ein Komma optional. Man darf es schreiben, aber Lua verlangt es nicht.
-
Besteht Interesse an einem Lua-Tutorial?
Ja. Das Schlüsselwort dafür heißt break Wenn du einen for-Schleifenzähler über die Schleife hinaus noch benötigst, musst du ihn - genau wie du vermutest - übergeben. Was du im while ... do Konstrukt stehen hast, ist kein Zähler, sondern eine Bedingung. Ob du diese Bedingung innerhalb der While Schleife durch Zählen oder anderweitig veränderst, macht keinen Unterschied. Die Variable wird nicht in der Bedingung erzeugt und ist nicht automatisch local.
-
Lua Tutorial
Variablen für Fortgeschrittene Lua Variablen können ohne Deklaration Daten jeden Typs speichern. Und man kann auch beim Überschreiben von Werten den Typ ändern. Ich kann beispielsweise eine Zahl mit einem String überschreiben, ohne dass Lua meckert. Das geht deshalb, weil in den Variablen selbst gar kein Wert steht, sondern nur eine Speicheradresse. Die Variable speichert nur, wo etwas steht aber nicht, was dort steht. Und Adressen sind immer gleich lang. Egal, ob sie auf eine Zahl, einen String oder etwas anderes zeigen. Variablen sind in Lua immer global definiert. Man muss ihnen bei der Deklaration das Schlüsselwort local voran stellen, um lokale Variablen zu erzeugen. function Test_a() a = 1 return a end function Test_b() local b = 1 return b end if Test_a() == a then print("a ist eine globale Variable") else print("a ist eine lokale Variable") end if Test_b() == b then print("b ist eine globale Variable") else print("b ist eine lokale Variable") end Funktionsargumente und Schleifenzähler sind automatisch lokale Variablen Lua erlaubt multiple Zuweisungen a, b = 2, 3 Damit lassen sich auch Werte tauschen: a, b = b, a Wenn man mehrere Variablen zugleich deklariert, dann kann man allen zusammen einmal das Schlüsselwort local voranstellen local a, b, c = 1, 2, 3
-
Lua Tutorial
Variablen im 3D-Modellbahn Studio Im MBS gibt es Daten, die man als User gerne auslesen und verwenden möchte. Zum Beispiel die Stellung eines Signals. Oder die Geschwindigkeit einer Lok. Oder der Name des Fahrzeugs auf einem Gleisstück. Damit man in der EV an diese Daten kommt, haben die Speicherplätze für diese Daten eigene Namen. Das sind also Variablen, deren Name schon im MBS festgelegt wurde. Wenn man davon absieht, dass die Namen dieser Speicherplätze schon festliegen und die Werte in diesen Speicherplätzen vom MBS stammen, unterscheiden sich diese Variablen nicht von solchen, die man selbst deklariert. Es sind Speicherplätze, die einen Namen bekommen haben, damit man sie im Programmcode oder in der EV verwenden kann. Ein Teil der Schwierigkeiten, welche manche User mit Variablen haben, stammen möglicherweise von den Namen dieser Variablen. Man muss die richtigen Namen kennen. Und das sind vielleicht nicht die Namen, welche man selbst ausgesucht hätte. An dieser Tatsache wird auch Lua nichts ändern. Wenn eine Person „Peter“ heißt, dann muss ich sie mit „Peter“ ansprechen. Auch, wenn ich finde, dass der Name „Klaus“ viel besser passen würde. Peter fühlt sich nur angesprochen, wenn ich ihn mit seinem Namen anrede. Welche MBS-Variablen es in V5 geben wird, weiß ich nicht. Aber sie werden eine wichtige Rolle spielen, weil man auch mit Lua die MBS Objekte steuern will. Das geht nur, wenn ich die Namen der einzelnen Objektparameter kenne. In Lua Skripten werden sowohl Variablen vorkommen, die vom MBS stammen als auch solche, die man selbst definiert. Und die müsst ihr unterscheiden können. Ihr müsst verstehen, wann ihr euch an vorgegebene Namen halten müsst und wann ihr eigene Namen definiert. Das ist nicht schwer. Es muss einem nur bewusst sein, dass es diesen Unterschied gibt.
-
Lua Tutorial
Variablen Bislang habe ich den Variablen kein eigenes Kapitel gewidmet. Normalerweise fängt man ein Tutorial damit an, dass man Variablen erklärt. Aber ich weiß, dass manche hier Abneigungen verspüren, wenn dieses Thema aufkommt. Und man müsste Variablen abstrakt und ohne passenden Zusammenhang erklären, wenn man ein Tutorial mit diesem Thema beginnt. Deshalb hatte ich mich für eine andere Reihenfolge entschieden. In den ersten Übungen habt ihr Variablen schon benutzt. Ihr habt sie kennengelernt, ohne dass ich sie im Detail erklärt habe. Und ihr habt schon den Zusammenhang gesehen, in dem man Variablen einsetzt. Variablen sind nichts anderes als Platzhalter. Wenn ich beim Entwurf einer Funktion bestimmte Inhalte noch nicht kenne, dann schreibe ich Platzhalter dorthin, wo später diese Inhalte eingesetzt werden sollen. Und damit ist im Prinzip schon erklärt, was eine Variable ist. Mehr steckt nicht dahinter. Man kann Variablen einen beliebigen Namen geben. Der darf aus einem einzelnen Buchstaben bestehen oder ein ganzes Wort sein. Aber der Name darf nur aus Buchstaben, Ziffern und dem Unterstrich bestehen. Und er darf nicht mit einer Ziffer beginnen. (Ich hatte das in einem früheren Kapitel schon einmal geschrieben. Aber es ist so wichtig, dass ich es hier noch einmal wiederholen möchte.) Vermeidet spezielle Buchstaben wie z.B. Umlaute oder das ß. Sicher kennt ihr von E-Mails das Problem, dass an Stelle solcher Buchstaben manchmal kryptische Zeichenfolgen auftauchen? Dasselbe könnte euch auch im Programmcode passieren und dann für Probleme sorgen.
-
Lua Tutorial
Lösungsbeispiele „Differenz21“ Beginnen möchte ich wieder mit dem Lösungsweg, der die Aufgabe „buchstäblich“ umsetzt: function Differenz21(n) Ergebnis = math.abs(21 - n) if n > 21 then Ergebnis = Ergebnis * 2 end return Ergebnis end Zuerst wird die Differenz von 21 und n gebildet und der Betrag dieser Differenz in einer Variablen Ergebnis gespeichert. Dann wird geprüft, ob n größer als 21 ist. Falls ja, dann wird der Wert in Ergebnis verdoppelt und wieder in Ergebnis gespeichert. Zuletzt wird der Wert von Ergebnis ausgegeben. Es wäre sauberer, Ergebnis als eine lokale Variable anzulegen. Aber mit der globalen Variable funktioniert das Skript ebenso gut. Drum habe ich mehr Wert auf ein leicht lesbares Beispiel gelegt. Unter anderem sollte dieses Beispiel dazu dienen, die math.abs() Funktion vorzustellen. Die ist praktisch und mit einem einfachen Beispiel, wie dem hier gezeigten, leicht zu verstehen. Aber für die gestellte Aufgabe kommt man auch ohne diese Funktion aus. function Differenz21(n) Ergebnis = 21 - n if n > 21 then Ergebnis = Ergebnis * -2 end return Ergebnis end Das Ergebnis von 21 - n kann ja nur dann negativ sein, wenn n größer als 21 ist. Und wenn man in diesem Fall das Ergebnis sowieso verdoppeln muss, dann kann man es auch mit -2 multiplizieren, um aus dem negativen einen positiven Wert zu machen. Damit entfällt die Notwendigkeit, den Betrag der Differenz zu bilden. Außerdem ist eine Überlegung wert, ob man den ursprünglichen Wert von n im weiteren Verlauf behalten muss. Falls nicht, dann kann man die Variable n selbst verändern und wieder auszugeben. function Differenz21(n) n = 21 - n if n < 0 then n = n * -2 end return n end Man spart so eine zusätzliche Variable ein. Und n ist, wie alle Funktionsargumente, eine lokale Variable. Es ist riskant, den Wert der ursprünglichen Variable zu ändern. Schnell übersieht man dabei, dass man den ursprünglichen Wert später noch benötigt. Im vorliegenden Fall für den Vergleich, ob n größer als 21 ist. Das letzte Beispiel funktioniert nur, weil ich diesen Vergleich durch einen anderen ersetzt habe. Denn wenn n größer als 21 war, dann ist das Ergebnis von 21 - n kleiner als 0. Alternativ kann man auch erst prüfen, ob n größer als 21 ist und dann entsprechend verzweigen function Differenz21(n) if n > 21 then return (n - 21) * 2 end return 21 - n end Durch den Tausch der beiden Werte in der Subtraktion entfällt in der dritten Zeile das negative Vorzeichen vor dem Multiplikator. Der Einzeiler für Fortgeschrittene kann so aussehen: function Differenz21(n) return n > 21 and (n - 21) * 2 or 21 - n end Ich hoffe, ihr hattet Spaß an diesen Knobeleien? In den nächsten Kapiteln will ich wieder ein paar Grundlagen zu Lua erklären.
-
Lua Tutorial
Differenz21 In dieser Aufgabe hat die zu definierende Funktion nur einen Parameter vom Typ "number". Ich gebe der Variable den Namen n. Die Funktion soll den absoluten Wert der Differenz zwischen 21 und n zurückgeben. Und falls n größer als 21 ist, soll dieser Wert verdoppelt werden. Als absoluten Wert bezeichnet man die positive Version einer Zahl. Ein anderer Ausdruck für den absoluten Wert ist "Betrag". Der Betrag von 5 ist 5 Der Betrag von -5 ist ebenfalls 5 Beispiele: Für n = 1 muss die Funktion den Wert 20 ausgeben Für n = 25 muss die Funktion den Wert 8 (das doppelte des Betrags von -4) ausgeben function Differenz21(n) end Lua bringt eine vordefinierte Funktion mit, die den Betrag einer Zahl bildet. Diese Funktion heißt math.abs() und ist eine von mehreren Funktionen aus der "math" Bibliothek. Deshalb hat sie diesen zweiteiligen Namen mit dem Punkt dazwischen. Dazu erkläre ich in späteren Kapiteln mehr. Ein Skript mit Prüfroutine hänge ich wieder an dieses Posting an. Viel Spaß beim Ausprobieren und Studieren. Differenz21.zip
-
Lua Tutorial
für Fortgeschrittene In Lua sind Variablen grundsätzlich global definiert! Mit Ausnahme der Funktionsargumente, die selbstverständlich lokale Variablen sind. Möchte man eine lokale Variable erzeugen, dann muss man dafür in Lua das Schlüsselwort local benutzen. Richtig müsste mein letztes Beispiel aus dem vorherigen Posting also lauten: function Wurf(a, b) local c = a + b if a == b then c = 2 * c end return c end Eine lokale Variable gilt nur innerhalb der Funktion und wird bei Verlassen gelöscht. Die Verwendung lokaler Variablen innerhalb von Funktionsdefinitionen vermindert das Risiko von Namenskonflikten (weil der Namensbereich auf die Funktion und ihre Unterfunktionen beschränkt ist) spart Speicherplatz (weil der Platz für diese Variable nach Verlassen der Funktion frei gegeben wird) beschleunigt das Programm (weil diese kurzlebigen Variablen im Prozessor-nahen Speicher angelegt werden.) Für die letzte Aufgabe gibt es noch einen weiteren, interessanten Lösungsweg. Er macht sich das besondere Verhalten von and und or zunutze, welches ich im Kapitel 2b or not 2b angesprochen hatte. function Wurf(a, b) return a == b and 4 * a or a + b end Wenn a == b wahr ist, dann ist das Ergebnis der and Verknüpfung der zweite Term 4 * a Und weil dieser Term auf jeden Fall wahr ist, wird der Term hinter dem or nicht mehr geprüft, sondern das Resultat der and Verknüpfung ausgegeben. Nämlich 4 * a, ganz wie gewünscht. Ist die erste Bedingung hingegen nicht wahr, dann ist das Ergebnis der and Verknüpfung auch nicht wahr. Und in diesem Fall wird der Term ausgegeben, der hinter dem or steht. Nämlich a + b. Dieser Weg ist kein bisschen schneller als die zuvor gezeigten. Das ist nur eine akademische Spielerei, die aber mächtigen Spaß machen kann und zu mehr Routine führt.
-
Lua Tutorial
Lösungsbeispiele zu "doppelte Summe" Zuerst möchte ich einen Lösungsweg zeigen, den ich häufig sehe. Er setzt den Aufgabentext "buchstäblich" um: function Wurf(Zahl_1, Zahl_2) if Zahl_1 == Zahl_2 then return (Zahl_1 + Zahl_2) * 2 else return Zahl_1 + Zahl_2 end end Wenn die beiden Zahlen gleich sind, dann bilde die Summe, vedopple sie und gib das Ergebnis aus. Andernfalls gib einfach die Summe der beiden Zahlen aus. Beachtet bitte, dass bei der Verdopplung in der dritten Zeile die Summe in Klammern stehen muss. In Lua gilt Punktrechnung vor Strichrechnung. Das heißt, dass ohne die Klammern nur die zweite der beiden Zahlen verdoppelt würde. Hier ist ein Vorschlag zur Vereinfachung des obigen Beispiels: In der zweiten Zeile wird geprüft, ob beide Zahlen gleich sind. Und die dritte Zeile wird nur dann ausgeführt, wenn diese Bedingung erfüllt war. Also ist Zahl_1 + Zahl_2 an dieser Stelle dasselbe wie Zahl_1 + Zahl_1 oder 2 * Zahl_1. Deshalb kann man die Rechenoperation in Zeile 3 vereinfachen. function Wurf(Zahl_1, Zahl_2) if Zahl_1 == Zahl_2 then return 4 * Zahl_1 else return Zahl_1 + Zahl_2 end end Ein weiterer Weg wäre der, dass man zuerst eine der beiden Zahlen ändert, falls beide gleich sind. Und dann die Summe bildet. function Wurf(Zahl_1, Zahl_2) if Zahl_1 == Zahl_2 then Zahl_1 = 3 * Zahl_1 end return Zahl_1 + Zahl_2 end Für das Ergebnis macht dieser unorthodoxe Weg keinen Unterschied. Man kommt damit genauso schnell und sicher zum Ziel wie mit den ersten beiden Wegen. Aber diese Fassung ist schwer nachvollziehbar und deshalb nicht wirklich ratsam. Trotzdem haben mir solche Gedankenexperimente geholfen, Lua und überhaupt das Programmieren besser zu verstehen. Deshalb möchte ich euch gerne dazu animieren, solche verschiedenen Lösungswege durchzuspielen. Mit diesen sehr einfachen Aufgaben, die nur wenige Zeilen Programmcode erfordern, kann man das gut machen. Die folgende Methode ist populär und gut lesbar: function Wurf(Zahl_1, Zahl_2) Ergebnis = Zahl_1 + Zahl_2 if Zahl_1 == Zahl_2 then Ergebnis = 2 * Ergebnis end return Ergebnis end Diesmal wird das Ergebnis in mehreren Schritten gebildet und in einer neuen Variable namens Ergebnis zwischengespeichert. Lua kann diese Variable gleich in der Funktion bilden. Man muss sie nicht erst deklarieren, wie das vor allem bei Compiler-Sprachen erforderlich ist. Man weist der Variablen einfach einen Wert zu und kann sie anschließend verwenden. Selbstverständlich kann diese Variable jeden beliebigen Namen haben und muss nicht zwingend Ergebnis heißen. Und genauso kann man übrigens auch die Namen der Funktionsargumente ändern. Diese Variablen existieren ja nur innerhalb der Funktion. Man kann das letzte Beispiel also auch so schreiben: function Wurf(a, b) c = a + b if a == b then c = 2 * c end return c end Dem einen oder anderen ist diese Schreibweise vielleicht einleuchtender. Weil die Formeln besser zutage treten. Nur den Namen der Funktion solltet ihr bitte beibehalten, wenn ihr mein kleines Testskript verwenden wollt. Denn das ist der Funktionsname, der weiter unten mit verschiedenen Beispielwerten aufgerufen wird.
-
Java API
Du findest Lua in sehr vielen Spielen wie z.B. Minecraft oder Factorio. Meines Wissens eignet es sich besonders gut für diese Art der Integration in Programme. Und es ist - wie Python - sehr Einsteiger-freundlich. https://en.wikipedia.org/wiki/List_of_applications_using_Lua#Video_games
-
Lua Tutorial
doppelte Summe Die dritte Aufgabe hat dasselbe Muster wie die vorherigen beiden. Aber die beiden Parameter beim Aufruf sind diesmal keine booleans (true oder false), sondern Zahlen. Die Funktion soll die Summe der beiden Zahlen zurückgeben. Und wenn beide Zahlen gleich sind, dann soll sie die Summe vor der Ausgabe verdoppeln. function Wurf(Zahl_1, Zahl_2) end Ich habe die Funktion "Wurf" genannt, weil die Aufgabe für ein Würfelspiel geeignet wäre. Der Spieler würde per Knopfdruck zwei Zahlen würfeln und die Funktion, welche ihr hier definiert, errechnet dann das Ergebnis. Ein Pasch zählt dabei doppelt. Im Anhang findet ihr wieder ein Skript mit angehängter Testroutine, welches ihr für die Prüfung eurer Lösungsansätze verwenden könnt. Ich freue mich über jeden Lösungsvorschlag, den ihr mir als Nachricht schickt. doppelte Summe.zip
-
Besteht Interesse an einem Lua-Tutorial?
Ich glaube, für eine ehrliche Antwort muss sich niemand entschuldigen. Und Lua muss dich nicht erschrecken. Weil es nicht erforderlich ist, dass man das lernt. Die V5 wird dir gewiss auch ganz ohne Lua viel Freude machen. Und du wirst auch ohne Lua Kenntnisse auf nichts verzichten müssen. Lua ist einfach nur eine weitere Möglichkeit der Anlagensteuerung und für diejenigen gedacht, denen diese Methode liegt. Es ist wie ein weiteres Musikinstrument. Man muss nicht alle Instrumente beherrschen, um Musik zu machen. Aber man kann eine größere Auswahl an Musik genießen, wenn alle Musiker viele verschiedene Instrumente zur Auswahl haben.
-
Besteht Interesse an einem Lua-Tutorial?
Stimmt. Das wüsste ich auch zu gerne. Motiviere ich die Leser? Oder verschrecke ich sie eher?
-
Lua Tutorial
Lösungsvorschläge für das Affentheater In dieser Aufgabe war, genau wie in der ersten, gefordert, dass die Funktion etwas zurückgeben soll. Und zwar soll sie true zurückgeben, wenn beide Parameter true sind. Wenn also beide Affen grinsen. Und die Funktion soll auch dann true zurückgeben, wenn beide Parameter false sind. Wenn also beide Affen nicht grinsen. Das kann man genau so in die Funktion schreiben: function Schwierigkeiten(Kaya_grinst, Toto_grinst) if Kaya_grinst and Toto_grinst then return true end if not Kaya_grinst and not Toto_grinst then return true end return false end Und weil die erste und die zweite Bedingung dieselbe Konsequenz haben, kann man sie auch in einer Bedingung zusammenfassen. function Schwierigkeiten(Kaya_grinst, Toto_grinst) if (Kaya_grinst and Toto_grinst) or (not Kaya_grinst and not Toto_grinst) then return true end return false end Beachtet bitte, dass in der Mitte ein or steht und kein and. Denn es reicht ja, wenn einer der beiden geklammerten Ausdrücke wahr ist. Umgangssprachlich würde man in der Mitte ein "und" benutzen: "Wenn beide Affen grinsen gib ein true zurück und wenn beide nicht grinsen, dann auch." Aber logisch wäre ein and die falsche Wahl, weil es bedeutet, dass beide Bedingungen zugleich erfüllt sein müssen. Weil jetzt der gesamte Ausdruck hinter dem if genau das ergibt, was wir als Antwort brauchen, kann man ihn auch direkt zurück geben: function Schwierigkeiten(Kaya_grinst, Toto_grinst) return Kaya_grinst and Toto_grinst or not Kaya_grinst and not Toto_grinst end Dabei kann man sogar die Klammern weglassen, weil das and stärker bindet als das or und das not stärker bindet als das and. Das heißt: Zuerst führt Lua die beiden not Operationen durch, dann die and Operationen und zuletzt die or Operation. Diese Schreibweise ist aber furchtbar unleserlich. Die erste Version mit den zwei einzelnen Prüfungen finde ich in diesem Punkt deutlich angenehmer. Deshalb habe ich überlegt, ob man die nicht noch etwas vereinfachen kann. Nehmen wir den Fall, dass Kaya grinst. Dann ist das gewünschte Ergebnis true, wenn Toto_grinst true ist. Und es ist false, wenn Toto_grinst false ist. Wir können also auf die and Verknüpfung verzichten und gleich Toto_grinst zurückgeben, falls Kaya_grinst wahr ist if Kaya_grinst then return Toto_grinst end Und wenn man auch für den Fall etwas definieren möchte, dass die Bedingung hinter dem if nicht erfüllt ist, dann gibt es in Lua dafür das Schlüsselwort else (zu Deutsch: "andernfalls" oder "sonst") Und was soll andernfalls passieren? Was ist als Ergebnis gefordert, wenn Kaya nicht grinst? Falls Toto_grinst jetzt true ist, dann ist das Ergebnis false. Falls aber Toto_grinst auch false ist und somit beide Affen nicht grinsen, dann ist das Ergebnis true. Für den Fall, dass Kaya nicht grinst, ist das Ergebnis also das Gegenteil von Toto_grinst. Es ist not Toto_grinst function Schwierigkeiten(Kaya_grinst, Toto_grinst) if Kaya_grinst then return Toto_grinst else return not Toto_grinst end end Verblüfft? Man kann sich aber auch ganz vom genauen Wortlaut der Aufgabe lösen und stattdessen schauen, was wirklich gefordert ist: Wenn beide Affen dasselbe tun, dann ist das Ergebnis wahr, sonst nicht. Dann müsste es doch auch genügen, wenn man die beiden Parameter vergleicht. function Schwierigkeiten(Kaya_grinst, Toto_grinst) return Kaya_grinst == Toto_grinst end Das funktioniert, ist wirklich gut lesbar und außerdem schön schlank. Vielen Dank @Andy für diese sehr schöne Einsendung. Ich hoffe, dass mit dieser zweiten Aufgabe noch deutlicher wird, was schon bei der ersten Aufgabe durchschien: Dass es nicht darum geht, für eine Aufgabe eine richtige Lösung zu finden. Und sich diese Lösung dann für die Zukunft zu merken. Das funktioniert einfach nicht. Es geht vielmehr darum, möglichst viele dieser Lösungsbeispiele zu durchschauen. Zu erkennen, was da jeweils im Code passiert und warum das funktioniert. Je klarer euch anhand der verschiedenen Beispiele wird, wie die Mechanismen funktionieren, desto leichter wird es euch fallen Skripte zu entwerfen, die zu euren konkreten Bedürfnissen passen. Und deshalb mag ich diese kleinen Übungen so sehr. Man kann anhand dieser Beispiele wunderbar demonstrieren, welche Denkansätze alle zum Ziel führen. Man kann die verschiedenen Lösungsvorschläge mit der eigenen Lösung vergleichen und vielleicht an der einen oder anderen Stelle denken: "Ah - der Weg ist auch nicht schlecht." Und man kann unterschiedliche Methoden sehr bequem ausprobieren. Viel Spaß bei euren Entdeckungen. Die dritte Aufgabe folgt morgen.
-
Lua Tutorial
Affentheater Die zweite Aufgabe ist der ersten sehr ähnlich. Diesmal geht es um die Affen Toto und Kaya, welche uns gerne Schwierigkeiten bereiten. Aber man kann es ihnen ansehen. Wenn beide grinsen oder wenn keiner von beiden grinst, dann stecken wir in Schwierigkeiten. Grinst einer der beiden Affen, aber der andere nicht, dann haben wir nichts zu befürchten. Der Funktionsrahmen sieht so aus function Schwierigkeiten(Kaya_grinst, Toto_grinst) end Die Funktion wird wieder mit zwei Parametern aufgerufen werden, die beide entweder true oder false sein können. Und sie soll true zurückgeben, wenn wir in Schwierigkeiten stecken oder false, falls nichts zu befürchten ist. Das Prinzip ist also dasselbe wie bei der vorherigen Aufgabe. Die möglichen Kombinationen aus true und false sollen nur diesmal zu anderen Ergebnissen führen. Deshalb muss man die beiden Parameter anders auswerten als beim ersten Mal. Im Anhang findet ihr wieder ein Skript mit angehängter Testroutine für die Prüfung eurer Lösungsansätze. Ich würde mich sehr freuen, wenn ihr mir eure Lösungsvorschläge per PN schickt. Affentheater.zip
-
Lua Tutorial
Lösungsansätze zur Aufgabe "Ausschlafen" Wenn man mein Testskript unverändert in das Lua-Demo Fenster kopiert, dann bekommt man diese Antwort: Das Programm wird fehlerfrei ausgeführt. Es enthält keine Syntaxfehler. Aber die Funktion tut noch nicht das, was sie tun soll. Weil die Funktion völlig leer ist, gibt sie auch nichts zurück. Und genau das steht in der Auflistung. Viermal ergeben die Parameter nil. Sie sollten aber in drei Fällen true und in einem Fall false ergeben. Was passiert, wenn man in die Funktion einfach return true schreibt? function Ausschlafen(Werktag, Urlaub) return true end Dann ist das Ergebnis nur noch in einem von vier Fällen falsch. Mit return kann man also dafür sorgen, dass die Funktion beim Aufruf etwas zurück gibt. Jetzt muss man dafür sorgen, dass sie abhängig von den beiden Argumenten Werktag und Urlaub das richtige zurück gibt. Wenn Urlaub wahr ist, dann muss die Funktion ein true zurückgeben. Denn dann kann man ausschlafen. Das könnte so aussehen function Ausschlafen(Werktag, Urlaub) if Urlaub then return true end end Beachtet bitte, dass man in der if ... then Zeile keinen Vergleich Urlaub == true benötigt. Denn dieser Vergleich liefert nur das, was in Urlaub schon drin steht. Ist Urlaub wahr, dann ist auch das Ergebnis des Vergleichs wahr. Ist Urlaub falsch, dann ist auch das Ergebnis des Vergleichs falsch. Der zusätzliche Vergleich erfordert zusätzliche Rechenzeit, bringt aber keinen Nutzen. Wenn man diese Funktion verwendet, dann ist das Ergebnis in zwei von vier Fällen falsch. Die Funktion gibt nil zurück, wenn Urlaub nicht wahr ist. Ist Urlaub wahr, dann ist das Ergebnis der Funktion richtig. Nun kann man den Werktag prüfen: function Ausschlafen(Werktag, Urlaub) if Urlaub then return true end if Werktag then return false end end Damit ist das Ergebnis schon in drei von vier Fällen richtig. Nur wenn kein Urlaub und kein Werktag ist, lautet das Ergebnis noch nil. Denn weder die erste, noch die zweite Bedingung ist erfüllt. Deshalb gibt die Funktion nichts zurück. Sie soll in diesem Fall aber true zurückgeben, weil man ausschlafen kann wenn kein Werktag ist. function Ausschlafen(Werktag, Urlaub) if Urlaub then return true end if Werktag then return false end return true end In dieser Form besteht die Funktion alle 4 Tests Dazu muss man wissen, dass ein return in einer Funktion dazu führt, dass die Funktion komplett verlassen wird. Alles, was nach dem return kommt, ignoriert Lua wenn die return Zeile ausgeführt wird. Deshalb wird der Werktag nicht mehr geprüft, wenn Urlaub wahr ist. Und deshalb wird die letzte Zeile nicht mehr ausgeführt, wenn Urlaub falsch, aber Werktag wahr ist. Das bedeutet, dass bei dieser Konstruktion die Reihenfolge wichtig ist. Wenn man sie vertauscht, dann erhält man zum Teil falsche Ergebnisse. function Ausschlafen(Werktag, Urlaub) if Werktag then return false end if Urlaub then return true end return true end Bei dieser Reihenfolge würde der Urlaub nicht mehr geprüft, wenn Werktag wahr ist. Der Wecker klingelt jetzt auch im Urlaub an Werktagen. Denn die erste Prüfung hat an Werktagen zur Folge, dass die Funktion sofort mit einem return false verlassen wird Jetzt kehrt die Prüfung bei Werktag bitte einmal ins Gegenteil. Testet, ob kein Werktag ist. function Ausschlafen(Werktag, Urlaub) if not Werktag then return true end if Urlaub then return true end return false end Das heißt, dass jetzt true zurückgegeben wird, wenn kein Werktag ist. Und wenn kein Werktag ist, dann ist es egal, ob Urlaub ist oder nicht. Und false wird nur dann zurückgegeben, wenn weder die erste, noch die zweite Bedingung erfüllt ist. Bei dieser Variante sind die beiden Prüfungen austauschbar. Und außerdem kann man sie jetzt in einer Prüfung zusammenfassen. function Ausschlafen(Werktag, Urlaub) if not Werktag or Urlaub then return true end return false end Und weil der gesamte Term not Werktag or Urlaub jetzt genau das ergibt, was wir als Antwort haben wollen, muss man auch keine if-Prüfung mehr durchführen. Man gibt einfach das Ergebnis der logischen Verknüpfung zurück function Ausschlafen(Werktag, Urlaub) return not Werktag or Urlaub end Manche setzen den Term hinter dem return in Klammern, weil andere Programmiersprachen das so fordern. In Lua ist das nicht erforderlich, aber erlaubt. Ich weiß, dass das alles abstrakt und für Einsteiger eine harte Nuss ist. Deshalb poste ich in den nächsten Tagen weitere Übungen dieser Art. Denn diese kleinen Beispiele enthalten im Kern genau das, was man auch für die Nutzung von Lua im MBS brauchen wird. Funktionen, die anhand von Parametern eine Entscheidung treffen und dann das eine oder andere tun. Es wird vermutlich Funktionen geben, die fertig definiert sind und nur mit geeigneten Parametern aufgerufen werden. So wie das bekannte print(). Und es wird vermutlich die Möglichkeit geben, aus der EV eine Funktion aufzurufen, die man an anderer Stelle selbst definiert. Ich weiß das nicht. Aber es ist sehr naheliegend, dass es so sein wird. Deshalb halte ich es für sinnvoll euch anhand kleiner Beispiele das grundlegende Prinzip zu zeigen. Und ich hoffe natürlich, dass ihr auch ein bisschen Spaß dabei habt.
-
Besteht Interesse an einem Lua-Tutorial?
@m.weber Danke für deine offenen Worte. Jetzt verstehe ich besser, warum ich angeeckt bin. Gruß Götz
-
Lua Tutorial
An dieser Stelle würde ich gerne ein paar kleine Übungen anregen. Denn das Konzept einer Funktion sowie die Auswertung von true und false sind für das Programmieren elementar wichtig. Die Übungen stammen alle von Nick Parlantes Website Codingbat Ich habe sie nur von Englisch nach Deutsch und von Python nach Lua übersetzt. Die erste Aufgabe lautet wie folgt: Schreibe eine Funktion, die anhand der beiden Argumente Werktag und Urlaub zurückgibt, ob man ausschlafen kann oder nicht. Man muss nur die Funktion definieren. Und der Rahmen ist schon vorgegeben. function Ausschlafen(Werktag, Urlaub) end Beim Aufruf werden die Variablen Werktag und Urlaub jeweils mit true oder false befüllt. An Werktagen darf man nur im Urlaub ausschlafen. Wenn kein Werktag ist, dann darf man immer ausschlafen. Die Aufgabe ist, zwischen die erste und letzte Zeile der Funktionsdefinition ein wenig Lua Code zu schreiben. Dieser soll Werktag und Urlaub auswerten und dann soll die Funktion je nach Ergebnis der Auswertung entweder ein true oder false zurückgeben. Man muss nur die Funktionsdefinition vervollständigen. Im Anhang füge ich ein kleines Testskript bei. Das kann man im oberen Teil entsprechend ergänzen und dann komplett in Lua-Demo, ZeroBrane, Notepad++ oder einem anderen Programm laufen lassen. Der untere Teil des Testskripts ist eine kleine Prüfroutine welche euch zeigt, ob eure Lösung funktioniert oder nicht. Diesen Teil dürft ihr bitte nicht verändern. Es wäre schön, wenn ihr mir Lösungsvorschläge nur als persönliche Nachricht schickt und sie nicht öffentlich postet. So hat jeder die Chance für sich zu überlegen, wie er die Aufgabe lösen möchte. Ausschlafen.zip
-
Besteht Interesse an einem Lua-Tutorial?
Es tut mir leid, @MakKucken Notepad++ und ZeroBrane sind meines Erachtens die beiden Editoren, die sich am besten für eigene Lua Experimente eignen. Und das auch nur für die verbleibende, kurze Zeit bis 3D Modellbahnstudio V5 verfügbar ist. Dann ist der enthaltene Editor sowieso die richtige Wahl, weil er die Besonderheiten unterstützen wird, die es für das Zusammenspiel von 3D MBS und Lua geben wird. Deshalb wollte ich dir empfehlen, bei einem der zwei genannten zu bleiben. Das ist doch kein Grund, gleich verschnupft zu reagieren. Gruß Götz
-
Besteht Interesse an einem Lua-Tutorial?
Bleib bei Notepad++ oder ZeroBrane. Je nachdem, was dir mehr zusagt. Stecke deine Energie lieber in das Erlernen von Lua selbst. Das wird dich weiterbringen, als ein Vergleich aller verfügbarer Editoren.
-
Lua Tutorial
2b or not 2b fragte sich ein Postbote im englischen Stratford upon Avon im Jahre 1584 beim Versuch, die handgeschriebene, unleserliche Adresse auf einem Brief zu entziffern. Damit inspirierte er nicht nur den jungen William Shakespeare zu seinem berühmten Monolog, sondern legte zugleich auch den Grundstein für viele Programmiersprachen. Neben dem and aus dem letzten Kapitel sind or und not die anderen zwei Operationen, die man benötigt um Bedingungen zu verknüpfen. Das englische Wort or entspricht dem deutschen oder. Die Verknüpfung zweier Elemente mit or bedeutet, dass mindestens ein Element wahr sein muss, aber auch mehr als ein Element wahr sein darf. Es ist kein entweder ... oder. Gleis_1_frei or Gleis_2_frei ist also auch dann true, wenn beide Variablen true sind. Ein entweder ... oder (man nennt das ein exklusives oder) gibt es in Lua nicht. Das Wort not entspricht dem deutschen Wort nicht. Mit not kann man ein boolean ins Gegenteil verwandeln. Es macht aus true ein false und umgekehrt. Wenn man zum Beispiel nur dann das Gleis 3 benutzen will, wenn Gleis 1 besetzt ist, dann könnte die Prüfung so aussehen if Gleis_3_frei and not Gleis_1_frei then Das not bindet stärker als die Vergleichsoperatoren. Wer das Ergebnis eines Vergleichs umkehren möchte, der muss den Vergleich in Klammern setzen not (a == b) -- ist dasselbe wie a ~= b Die Bedeutung von and, or und not ist einfach zu verstehen. Aber daraus die logisch richtige Kombination zu bilden, fällt manchmal auch erfahrenen Programmierern schwer. Deshalb werde ich in den nächsten Tagen ein paar sehr einfache Übungen dazu vorstellen. für Fortgeschrittene! Die logischen Operationen and und or liefern nicht immer ein boolean. Mit and bekommt man das zweite Element zurück, wenn beide Elemente wahr sind. Mit or bekommt man das erste wahre Element zurück. Dazu muss man wissen, dass jeder Wert, der in einer Variable gespeichert ist, in Lua als wahr gilt. Nur nil und false gelten als falsch. Eine Zahl ist also true. Und im Gegensatz zu anderen Programmiersprachen wertet Lua auch die 0 als true. Ein String ist ebenfalls true. Auch ein Leerstring "". Das Ergebnis von true and 1 ist 1, nicht true! Das Ergebnis von 0 or 1 ist 0 Das Ergebnis von 0 and 1 ist 1, nicht false! Das Ergebnis von Test or 1 ist 1, wenn Test noch keinen Wert hat bzw. noch nicht deklariert ist. Das Ergebnis von Test or 1 ist der Inhalt von Test, wenn dieser Inhalt nicht nil oder false ist. Das Ergebnis von "Toby" or not "Toby" ist "Toby" Das Ergebnis von 2b or not 2b ist eine Fehlermeldung, weil kein Variablenname mit einer Zahl beginnen darf! Wenn das Ergebnis einer Verknüpfung feststeht, dann werden die restlichen Elemente nicht mehr geprüft. Das bedeutet, dass Lua bei einem and aussteigt, wenn das erste Element false ist. Das Ergebnis der and Operation kann nicht mehr true sein, wenn ein Element false ist. Wird das zweite Element durch einen Funktionsaufruf gebildet, dann findet dieser Funktionsaufruf in diesem Fall nicht statt. Bei einem or steigt Lua entsprechend beim ersten wahren Element aus. Ist das erste Element true, dann wird eine Funktion, die das zweite Element liefern soll, nicht mehr ausgeführt. Ich glaube, dass das in vielen anderen Programmiersprachen genauso gehandhabt wird. Wenn man das versteht, dann kann man es sich zunutze machen. Wenn man es ignoriert, dann beißt es einen irgendwann in den Hintern ;-)
-
Oberleitung V4
@Andy Bei Lokschuppen mit Fahrleitung ist eine kleine Aussparung für den Fahrdraht in der Tür. Bei Lokschuppen ohne Fahrdraht werden kleine Akkuschlepper eingesetzt.
-
Besteht Interesse an einem Lua-Tutorial?
Ich denke, es ist alles korrekt. Das Fenster schließt selbständig, weil das Programm beendet ist.