[[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 end
auf 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.