• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

Schleifen programmieren

kansu_makugen

Geocacher
Tach allerseits,

ich versuche mich gerade am einem Wherigo und brauche für ein Rätsel ein Schleife (While-do oder repeat-until). Die gängigen Builder bieten da ja, wenn ich das richtig verstanden hab, keine Möglichkeit, also muss man den Code manuell schreiben. Ich hab schon ein wenig Erfahrung mit Programmieren und finde LUA jetzt auch nicht so schwierig.
Zurück zu den Loops. Für das besagte Rätsel habe ich eine MessageBox mit zwei Buttons im Builder erstellt. Je nach dem, welcher Button geklickt wird, werden bestimmte Variablen miteinander verrechnet. Der Loop soll dann solange durchlaufen werden, bis ein bestimmter Wert erreicht ist. Das kann nach fünf Durchläufen sein, aber auch erst nach 40-50, ja nach dem, wie sich der Spieler anstellt. Die MessageBox wird also innerhalb des Loops aufgerufen. Das Problem dabei ist aber, dass der Aufruf der MsgBox den Loop nicht unterbricht und dieser munter weiterläuft. In einem anderen Thread ( http://www.geoclub.de/viewtopic.php?f=74&t=49440 ) wurde schon ein ähnliches Problem durchgekaut, aber das hilft mir in meinen Fall auch nich weiter. Hier also meine Frage: Hat jemand Erfahrung mit Loops und evtl. eine Lösung parat, wie man diesen unterbrechen kann, um auf eine Eingabe zu warten?

Ich sach schon mal Danke!
Grüße
 

hihatzz

Geomaster
Hallo,
wie im anderen Thread beschrieben scheint mir das mit der while-loop bei Lua nicht so einfach zu sein.
Was du machen kannst ist bei Fehleingabe/Wert noch nicht erreicht wird derselbe Input wieder aufgerufen. Da das ein iterativer Aufruf ist (Input ruft sich selbst auf) weiss ich nicht wie oft das geht, bei anderen Programmiersprachen hängt das von der Stackgröße ab, bei Lua kenn ich mich leider nicht so aus.
Hier ist ein Urwigo-Tutorial auf youtube:
link

Ist zwar auf holländisch (glaub ich zumindest) man kann es aber trotzdem gut verstehen.
Schau dir den else-Zweig an (Message "Hellaas niet goed, probeer het noog eer", also so ungefähr "Nicht gut, probier es nochmal")
 
OP
kansu_makugen

kansu_makugen

Geocacher
Danke erstmal,

der Vorschlag mit der sich selbstaufrufenden Message ist wohl 'ne Möglichkeit, aber halt eine sehr unsaubere. Ich werds mal versuchen. Ist halt schwierig, weil ich bei dem Rätsel drei Variablen miteinander verrechne und es nur bei einem einzigen Wert weitergehen soll. Ich hab auch schon versucht, die Zone nach jeder Eingabe zu de- und wieder reaktivieren, weil die MessageBox beim Betreten der Zone ausgelöst wird, aber da hat natürlich auch nicht funktioniert. Wäre ja auch zu schön gewesen. Eine Idee wäre auch noch, die MsgBox aufzurufen, wenn sich der Wert einer oder mehrerer Variablen ändert. Muss ich mal testen...
 

Krolock

Geocacher
Wie wäre es denn, wenn du die Rekursion auf eine bestimmte Anzahl einschränkst. D.h. wenn du zum 15 Mal den Input aufrufst, brichst du das ganze ab und der Spieler muss die Routine erneut aufrufen (Einmal raus aus der Zone und wieder rein, oder ein Kommando auslösen) Wenn du das dem User gut verkaufst (Strafrunde laufen, kurz verschnaufen ....) sollte das kein Problem sein. So verringerst du die Gefahr des StackOverflows.

Ansonsten siehe die Idee von sTeamTraen im anderen Thread auch nicht schlecht aus. Durchbreche die asynchrone Verarbeitung nach dem Input, bis dieser die wait-Bedingung aufheben.
Ist ein ganz normales Synchronisationsproblem.
 

bodenseepingu

Geomaster
Hallo,

ich hab das Problem zwar nicht verstanden, habe aber mit dem Geo-Memory einen play anywhere WIG erstellt, bei dem (so bilde ich mir es ein) ein ähnlicher Fall vorliegt.

Ich habe eine Message-Box, die hat für ein Memory-Spiel einen "aufdecken" Button.
Diese Message-Box läuft jetzt zwar nicht in einer Loop aber in einem Timer mit Intervallzeit von 1 Sec. - was für User-Reaktionen ja hinreichend kurz ist...

Nur dann wenn tatsächlich Aufdecken gedrückt wird, wird die Karte auf der der Benutzer steht auch wirklich aufgedeckt...

Hier der Code-Ausschnitt (Timer-Routine in LUA):
Code:
function objKartepruefen:OnTick()

     

       local dist = Wherigo.Distance(0, 'm') 

       for i = 1, objAnzahlPaare * 2, 1 do

         local d, b = Wherigo.VectorToPoint(objSpielkartenlocationstbl[i], Player.ObjectLocation)

         local dn = d:GetValue 'm'

        

         if dn <= objDistanzzuKarte then           

             if objaktuelleSpielkarte ~= i then

                  print("neue Karte betreten"..dn)

                  objaktuelleSpielkarte = i

                  --objMemoryZelle.Visible = true

                  objMemorykarte.Active = false

                  objMemorykarte.OriginalPoint = Wherigo.TranslatePoint(objSpielkartenlocationstbl[i], dist, 0)

                  objMemorykarte.Points = objSpielkartenpointstbl[i]

                  objMemorykarte.Active = true

                  local msg = "Du bist an der Spielkarte Nummer "..objSpielfeldbezeichnung[objaktuelleSpielkarte]

                  local media

                  local but

                  if objSpielkartenaufgedeckttbl[i] then

                     msg = msg.." , diese ist aufgedeckt"

                     media = GetKarte(objSpielkartenfeldtbl[i])

                     but="-"

                     --Wherigo.MessageBox{ Text=msg, Media=GetKarte(objSpielkartenfeldtbl[i]), }

                     --objMemoryZelle.Commands.cmdAufdecken.Enabled = false

                  else

                     but ="aufdecken"

                     media = objMemorybild

                     --Wherigo.MessageBox{ Text=msg, Media=objMemorybild, }

                     --objMemoryZelle.Commands.cmdAufdecken.Enabled = true

                  end

                  _Urwigo.MessageBox{

			Text = msg, 

			Media = media, 

		       Buttons = {

			    but, 

			    "Dialog schliessen"

		        }, 

		       Callback = function(action)

			 if action ~= nil then

				if action == "Button1" then

				      if  not objSpielkartenaufgedeckttbl[i] then

				  	   KarteAufdecken()

				      end

				end

			 end

		       end 

	           }

                  Logbuchaufzeichnung(msg)

             end          

         end

     end

  

end
 
OP
kansu_makugen

kansu_makugen

Geocacher
Moinsen,

jo, die Idee mit dem Timer kam mir auch. Ich hab da mal ein bisschen rumprobiert und bin auf eine Lösung gekommen.

Zuerst starte ich einen Timer, der bei mir 30s läuft. Wenn er abläuft, ruft er sich einfach selber wieder auf, startet also neu.
Mit dem Timerstart wird eine MsgBox / InputBox (was auch immer man will) aufgerufen. Wenn man dort keine Eingabe macht, oder zu lang wartet, startet der Timer sich ja selbst neu und die MsgBox damit auch.
Wenn der Spieler eine Eingabe macht, wird der Timer gestoppt. Dann wird bei mir eine User Function aufgerufen, die ich für das Rätsel geschrieben hab. Hier geh ich mal nicht ins Detail ;) In der Function wird ein bisschen rumgerechnet. Danach wird geprüft, ob der Spieler alles richtig gemacht hat.
Wenn er hat, Wird das nächste Ereignis ausgelöst, wenn nicht, dann wird halt der Timer gestartet und alles geht von vorne los.

Ist halt ein bisschen umständlich, aber es funzt. :)
 

Krolock

Geocacher
Kansu_Makugen schrieb:
Wenn man dort keine Eingabe macht, oder zu lang wartet, startet der Timer sich ja selbst neu und die MsgBox damit auch.
Ist das nicht ein wenig User unfreundlich? Ich stelle mir gerade vor, dass ich ein längeres Wort (sagen wir 10 Buchstaben) eingeben muss und beim 9. Buchstaben ist auf einmal meine Eingabe weg, weil da gerade der Timer einen neuen Input auslöst. :motz:

Der Timer wird ja erst beendet, wenn die Eingabe mit OK weggeschickt wurde.
 
OP
kansu_makugen

kansu_makugen

Geocacher
Nö, du musst ja nichts eingeben sondern kriegst 'nen Multiple Choice Input vorgesetzt. Ist also kein Problem.
 
Oben