[[http://www.siedler-games.de|{{:sg-link.jpg|}}]] ====== Schleifen ====== [[http://www.siedler-portal.de/vb3/sendmessage.php?do=mailmember&u=1172|Ritter Lanzelot ]] \\ -------------------------------------------------------------------------------- FIXME Schaut gut aus. Vielleicht noch ein Beispiel, in dem ein String mit fortlaufender Zahl generiert wird. Schleifen sind eine wunderbare Erfindung einem viel Tipparbeit zu ersparen. Es **lohnt sich immer** , wenn man mehrfach das Gleiche macht, eine Schleife dazu zu benutzen. \\ \\ Die Arten: |Der Anfang | Das Ende ^ Kurzbeschreibung ^ ^for - Schleife| end |Schleife mit einem Zähler von bis und einer Sprungvariablen (step genannt)| ^while - Schleife| end |Schleife mit einer Bedingung| ^repeat - Schleife| until |Schleife mit einer Bedingung, die aber auf jedenfall mindestes einmal durchlaufen wird| ==== for ==== ---- |for i = 1, 4, 0.5 do --Arbeitsanweisung end |Mit "i" von 1 bis 4, in Schritten von 0.5, mache: --Arbeitsanweisung Verändere i (hier + 0.5), gehe nach oben; oder wenn i == 4 dann Ende| Das for-Statement hat zwei Formen: eine numerische und eine generische. Als Mapper benutzt man den numerischen. Die numerische wiederholt immer wieder einen Codeblock, solange eine Kontrollvariable einer festgelegten arithmetischen Gleichung noch entspricht. Viele von Euch haben sicherlich schon einmal den Teil for i = 1, 4 do EnlargeArmy(armyOne,troopDescription); end in einer Funktion CreateArmy() gelesen oder ihn kopiert, ohne so recht zu wissen, was er bedeutet. In der Karte ScriptExample wird darauf hingewiesen, dass in der Schleife das selbe passiert, als wenn man EnlargeArmy(armyOne,troopDescription); EnlargeArmy(armyOne,troopDescription); EnlargeArmy(armyOne,troopDescription); EnlargeArmy(armyOne,troopDescription); schreiben würde. Es wird also 4x ein Hauptmann mit Truppe zur Armee hinzu gefügt wird. \\ Die Definition einer For-Schleife ist for Name = exp , exp [ , exp ] do block endauf Deutsch: var für gewünschte Startzahl, limit für gewünschte Endzahl und step für gewünschte Schrittgröße for Name = var , limit [, step] do EnlargeArmy(armyOne,troopDescription) end im Beispiel von oben wird also bei 1 (var) begonnen, die Schleife läuft so oft, bis 4 (limit) erreicht ist und es wird immer um 1 (step) erhöht >>( **1** ist für step Standard und steht deshalb in eckiger Klammer. Alles was in Erkärungen in eckigen Klammern steht muss nicht unbedingt geschrieben werden) === Für uns wichtiges Beispiel === Wir haben ein paar Diebe die sind durchnummeriert von Dieb1, Dieb2, ..., bis Dieb 20. \\ Jetzt wollen wir irgendwann wissen ob alle noch am Leben sind. Ohne Schleife müßten wir dann schreiben if IsDead("Dieb1") then --Anweisung end if IsDead("Dieb2") then --Anweisung end . . . if IsDead("Dieb20") then --Anweisung end oder if IsDead("Dieb1") or IsDead("Dieb2") ... or IsDead("Dieb20") then --Anweisung end Viel Schreib- und Kopierarbeit. \\ Mit einer Schleife geht das ganz einfach for i = 1, 20 do if IsDead( "Dieb"..i ) then -- Hier wird "Dieb" mit i verbunden. Bei i = 5 >> "Dieb5" -- Anweisung end end Man kann das auch mit den anderen machen. dann muß man sich den Zähler aber selbst basteln. \\ Also besser mit **for**. ==== for – Schleife (generische Form) ==== FIXME[[\\ for ''variable'', wert in myTable do \\ Der Bezeichner ''variable'' ist unglücklich gewählt. Eine Variable ist auch ''wert'' oder myTable. Möchte man aus dem Englischen übertragen so wird "Key-Value-Pair" zu "Schlüssel-Werte-Paar". Zu ''Schlüssel'' kann man auch Index sagen. Außerdem sollte aus Kompatibilitätsgründen pairs() auf das Table angewendet werden. Das hat dir Chromix aber schon gesagt.\\ ]]FIXME Mit der numerischen Form konnten wir alle tables in der Art: myTable[nummer] durchgehen. Mit dieser Art von for – Schleife können wir aber solche tables nicht durchgehen: myTable.meinName Genau das kann aber die generische Form der for – Schleife. for variable, wert in myTable do Block end Diese Schleife geht, ungeachtet ob es sich um ein numerisches **table** oder ein **table** mit Namen handelt, jedes Teil des tables durch. Beispiel: Wir erzeugen ein table mit den Wochentagen tage = {"Sonntag", "Montag", "Dienstag","Mittwoch", "Donnerstag", "Freitag", "Samstag"} FIXME da muß ich noch ändern, Morgen Jetzt liegt ein table in dieser Form vor: tage[1] = "Sonntag" tage[2] = "Montag" tage[3] = "Dienstag" tage[4] = "Mittwoch" tage[5] = "Donnerstag" tage[6] = "Freitag" tage[7] = "Samstag" Noch ein numerisches table Wir machen eine generische Schleife. Dazu müssen wir nicht wissen, wie groß das table ist. Es wird ja jedes Element durchgegangen. tagesZahlen = {} for variable, wert in tagesZahlen do tagesZahlen[wert] = variable end Was geschieht: -- wir machen ein leeres table (tagesZahlen) -- jetzt geht die Schleife jeden Teil des Tables durch -- in der Variablen variable steht jedes Mal womit wir diesen Teil ansprechen können. In unserem Fall ist das jetzt die Zahl [1…7] -- in der Variablen wert steht jedes mal der Inhalt den Tables mit der entsprechenden Nummer [Sonntag … Samstag] -- im Block erzeugen wir dann jeweils ein Teil des Tables tagesZahlen in der Form: tagesZahlen.Sonntag = 1 ….. o tagesZahlen.Samstag = 7 Durch die Schleife: for i,v in tage do tagesZahlen[v] = i end haben wir gesehen, dass es noch eine andere Form gibt ein table mit Namen zu erzeugen • tagesZahlen.Sonntag = 1 -- kennen wir • tagesZahlen["Sonntag"] = 1 -- haben wir jetzt kennen gelernt • tagesZahlen = {Sonntag = 1} -- geht genau so Sehr vielseitig. Nicht wahr? Immer so nutzen, wie wir es gerade brauchen können. ==== while ==== ---- Die ''while-Schleife'' macht etwas **solange wie** eine Bedingung erfüllt ist. \\ \\ |while a == 1 do --Arbeitsanweisung end |Solange **wie** a gleich 1 ist mache: --Arbeitsanweisung Gehe nach oben oder a ist gleich 1 dann Ende| Kommt das Programm an der Schleife an, und a ist schon 1, dann wird nichts gemacht. \\ \\ Die Bedingung die erfüllt sein muß, um zu beenden, kann alles Mögliche sein. Sie ist nicht auf Zahlen beschränkt. Eine andere Bedingung wäre z.B. IsDead("Dario"). Also **solange wie** Dario tot ist mache. U.S.W. man könnte den Code der o.g. For-Schleife auch so schreiben: -- Deklarieren der Variablen var = 1; limit = 4; step = 1; -- nun die eigentliche Arbeit der Schleife: -- SOLANGE ( step größer als 0 UND var kleiner / gleich limit [ zum Hochzählen] ) ist -- ODER ( step kleiner / gleich 0 UND var größer / gleich limit [ zum Herunterzählen ] ) DANN while ( step > 0 and var <= limit ) or ( step <= 0 and var >= limit ) do -- der Block EnlargeArmy(armyOne,troopDescription); -- addiere step zu var var = var + step; end im Falle von for i = 1,4,1 do EnlargeArmy(armyOne,troopDescription); end würde das in Schritten so aussehen: Code:( **auf die Zahl -> drücken, um anzusehen**) ((**Zurück auf die Zahl <- drücken**1. Runde: while ( 1 > 0 and 1 <= 4 ) or ( step <= 0 and var >= limit ) do EnlargeArmy(armyOne,troopDescription); var = 1 + 1 -- -> 2 end 2. Runde: while ( 1 > 0 and 2 <= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 2 + 1 -- -> 3 end 3. Runde: while ( 1 > 0 and 3 <= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 3 + 1 -- -> 4 end 4. Runde: while ( 1 > 0 and 4 <= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 4 + 1 -- -> 5 end Abbruch, da jetzt var = 5 und somit nicht mehr kleiner oder gleich 4 ist.)) Die While-Bedingung ist //wie alle Schleifen// auch geeignet um etwas herunter zu zählen bis zu einem bestimmten Limit, dann muss step aber negativ sein: (geht in der for-Schleife aber bequemer) \\ Beispiel: wir starten bei 10 (var) und zählen bis 4 (limit) in Schritten von -2 (step) Code:( **auf die Zahl -> drücken, um anzusehen**) ((**Zurück auf die Zahl<- drücken**1. Runde: while ( step > 0 and var <= limit ) or ( -2 <= 0 and 10 >= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 10 + (-2); -- -> 8 end 2. Runde: while ( -2 <= 0 and 8 >= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 8 + (-2); -- -> 6 end 3. Runde: while ( -2 <= 0 and 6 >= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 6 + (-2); -- -> 4 end 4. Runde: while ( -2 <= 0 and 4 >= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 4 + (-2); -- -> 2 end Abbruch, da var mit 2 nun nicht mehr größer/gleich 4 ist Man könnte natürlich auch für step eine positive Zahl nehmen und den Block so schreiben: while ( step > 0 and var <= limit ) or ( 2 >= 0 and 10 >= 4 ) do EnlargeArmy(armyOne,troopDescription); var = 10 - 2; -- -> 8 end)) ==== repeat ==== ---- Die ''repeat-Schleife'' macht etwas ** solang bis** eine Bedingung erfüllt ist. \\ \\ |repeat --Arbeitsanweisung until a == 1 |Solange **bis** a gleich 1 ist mache: --Arbeitsanweisung Gehe nach oben oder a ist gleich 1 dann Ende| Kommt das Programm an der Schleife an, und a ist schon 1, dann wird //im Gegensatz zu While-Schleife// einmal die Anweisung gemacht. Die Bedingung die erfüllt sein muß, um zu beenden, kann alles Mögliche sein. Sie ist nicht auf Zahlen beschränkt. Eine andere Bedingung wäre z.B. IsDead("Dario"). Also **solange bis** Dario Tot ist mache. U.S.W.