Ich verstehe keine Rekursion

02/15/2015 02:40 RF1T2#1
Hi
hab ein bisschen Angst das zu fragen weil ich die ganzen Threads gesehen hab in denen noobs wie ich geflamet wurden wegen Fragen zu Rekursion^^

ok ich glaub ich poste das Script mit der Frage


was mache ich falsch?
Code:
#include <GUIConstantsEx.au3>

GUICreate("Air", 500, 100)
GUICtrlCreateLabel("[F1] - Start", 8, 8)
GUICtrlCreateLabel("[ESC] - Ende", 8, 48)
GUISetState(@SW_SHOW)

HotKeySet("{F1}", "Start1")
HotKeySet("{ESC}", "Ende")

While 1
	Sleep(500)
WEnd

Func Ende()
	Exit
EndFunc



Func Start1()




	MouseClick("Left",1676, 361)

	Sleep(2000)

	MouseClick("Left",992, 514)

	Sleep(17000)

	MouseClick("Left",1681, 171)

	Sleep(1000)

	MouseClick("Left",1900, 277)

	Sleep(10000)

	MouseClick("Left",1790, 313)

	Sleep(4000)

_array1()

EndFunc




;------------------------------------------------------------------

Func _array1()
	$PixelPosColor0 = PixelSearch(38 ,119 ,809 ,602 ,0x3F2736 ,3 )

Select

   Case	IsArray($PixelPosColor0) 
   MouseClick("left", $PixelPosColor0[0], $PixelPosColor0[1], 1, 0)
   Sleep(3000)
   Start2()

   Case	Else
			Send("{Left down}")
			Sleep(200)
			Send("{Left up}")
			Sleep(500)
			_array1()


EndSelect
EndFunc



;-----------------------------------------------------------------

Func Start2()
	Sleep(13500)

	MouseClick("Right",711, 226)

	Sleep(100)

	MouseClick("Left",707, 332)

	Sleep(1500)

	MouseClick("Left",1144, 139)

	Sleep(2500)
	
	MouseClick("Left",1674, 173)

   Sleep(1000)

	MouseClick("Left",1905, 281) ;safetyclick
	
	sleep(6000)
	
	Start3()

EndFunc

;part-----------------

Func Start3()


	Sleep(1000)

	Send("{Up down}")
	Sleep(1000)
	Send("{Up up}")
	_array2()


EndFunc

Func _array2()
	$PixelPosColorMark0 = PixelSearch(1664, 160, 1904, 239, 0x58CCF0 , 0)
	$PixelPosColorMark1 = PixelSearch(1661, 158, 1752, 374, 0x58CCF0 , 0)
	$PixelPosColorMark2 = PixelSearch(1835, 160, 1905, 365, 0x58CCF0 , 0)
	$PixelPosColorMark3 = PixelSearch(1662, 296, 1904, 370, 0x58CCF0 , 0)
	$PixelPosColorMark4 = PixelSearch(1674, 172, 1904, 370, 0x63D5FC , 0)

Select
	Case		IsArray($PixelPosColorMark0) 
	MouseClick("left", $PixelPosColorMark0[0], $PixelPosColorMark0[1], 1, 0)
	Sleep(3000)
	_array2()

	Case		IsArray($PixelPosColorMark1)
	MouseClick("left", $PixelPosColorMark1[0], $PixelPosColorMark1[1], 1, 0)
	Sleep(3000)
	_array2()

	Case		IsArray($PixelPosColorMark2) 
	MouseClick("left", $PixelPosColorMark2[0], $PixelPosColorMark2[1], 1, 0)
	Sleep(3000)
	_array2()

	Case		   IsArray($PixelPosColorMark3) 
	MouseClick("left", $PixelPosColorMark3[0], $PixelPosColorMark3[1], 1, 0)
	Sleep(3000)
	_array2()


	Case		IsArray($PixelPosColorMark4)
	MouseClick("left", $PixelPosColorMark4[0], $PixelPosColorMark4[1], 1, 0)
	Sleep(7500)
	Start4()


	Case	 Else
	Send("{Left down}")
	Sleep(100)
	Send("{Left up}")
	_array2()
	
	
EndSelect
EndFunc


Func Start4()
$PixelPosColor1 = PixelSearch(169, 202, 1878, 961, 0x566FB1, 1)

Select

	Case		IsArray($PixelPosColor1)
	MouseClick("left", $PixelPosColor1[0], $PixelPosColor1[1], 1, 0)
	Sleep(5000)
	Start5()

	Case	 Else

	Send("{Left down}")
	Sleep(100)
	Send("{Left up}")

	Sleep(500)

	Start4()

	

Endselect
EndFunc

Func Start5()
	Sleep(1000)

	MouseClick("Left", 1675, 177)
	
	Sleep(1000)
	
	MouseClick("Left", 1111, 426)

	Sleep(5000)


	Start1()

EndFunc
gerne nehme ich auch jede Form von Kritik an
edit: danke snow fürs ordentlich machen
02/15/2015 03:50 alpines#2
Hier wird nicht geflamed, hier wird gelernt.

Was gibts da nicht zu verstehen. Damit dein Speicher nicht überläuft darfst du ein höchstens ein Rekursionslevel erreichen was von AutoIt vorgegeben ist. Das ist unterschiedlich bei x86 und x64 Systemen.

Das Problem bei dir ist, das er die Funktionen immer wieder und wieder called ohne sie vorher zu returnen, also pack das ganze lieber in eine Schleife mit einer Variable die bestimmt in welcher Funktion er laufen würde nur in der Schleife.
02/15/2015 13:49 VisionEP1#3
Um Rekursion zu verstehen musst du erst mal Rekursion verstehen....
02/15/2015 16:32 warfley#4
Wenn du deinen Code formatiert in einem Code-Tag posten würdest wäre das schonmal ein guter Anfang. Noch besser wäre wenn du nur die entsprechende Methode posten würdest.
02/15/2015 16:34 RF1T2#5
ok denke habs verstanden nur eine Sache zur Sicherheit: Mit Return meinst du das Ende einer Func oder tatsächlich den Befehl?
Danke so oder so hat eig schon geholfen :)

Edit:@warfley sry bin überfordert nächstes mal bestimmt :X
Edit: achso quatsch stimmt ja, hab nach Kritik gefragt, alles ok^^
02/15/2015 16:48 alpines#6
Du darfst die Funktionen nicht so oft callen. Löse das ganze lieber in einer Schleife mit einem Modusvariable und dann hast du auch keine Rekursion mehr.
02/15/2015 17:02 snow#7
Ich habe mal das code-Tag eingefügt.

Rekursion ist der immer wieder auftretende Aufruf einer Funktion mit einem eindeutigen Abbruchkriterium. Ohne Abbruchkriterium endet die Rekursionsschleife nie und dein Stack läuft irgendwann über.

Die Fakultät wird gerne als Beispiel dafür verwendet (auch wenn es verdammt ineffizient ist):

Code:
func nfac(n: Int) -> Int {
	if n < 2 {
		
		return 1
	} else {
		
		return n * nfac(n - 1)
	}
}
Beim Aufruf nfac(3) wird die Abbruchbedingung nicht erfüllt, also erfolgt der Aufruf 3 * nfac(3 - 1).
Die Abbruchbedingung wird ebenfalls nicht erfüllt, also erfolgt 2 * nfac(2 - 1).
Jetzt wird die Abbruchbedingung erfüllt, also 1.

Ausgeschrieben sieht das so aus: nfac(3) = 3 * nfac(2), nfac(2) = 2 * nfac(1), nfac(1) = 1, also 3 * 2 * 1 = 6.

Dein Problem ist, dass die Folge der Funktionsaufrufe nie endet (da keine Abbruchbedingung vorhanden) und das kann selbst der stärkste Computer nicht auf Dauer durchhalten.
02/15/2015 18:40 RF1T2#8
danke für die hilfe freunde :)
02/16/2015 19:51 RF1T2#9
Ist der Gedanke hierbei so ok?

Code:
Func _array1()
	$PixelPosColor0 = PixelSearch(38 ,119 , 1615, 872, 0x412F4E, 1)

Select

   Case	IsArray($PixelPosColor0)
   MouseClick("left", $PixelPosColor0[0], $PixelPosColor0[1], 1, 0)
   Sleep(3000)
Start2()

   Case	Else
		Do
			Send("{Left down}")
			Sleep(200)
			Send("{Left up}")
			Sleep(500)
		Until IsArray($PixelPosColor0)
		_array1()

EndSelect
EndFunc
Es scheint nie bis _array1() zu kommen aber hilft das ausreichend gegen Rekursion?

Bei folgener Func bin ich mir sehr unsicher und konnte nach viel rumprobieren nur etwas hinbekommen was möglichst wenig nicht funktioniert:
Code:
Func Start2()
	
	$PixelPosColorMark1 = PixelSearch(1660, 159, 1911, 218, 0x0D9DC0 , 0);oben
	$PixelPosColorMark1 = PixelSearch(1660, 159, 1720, 376, 0x0D9DC0 , 0);links
	$PixelPosColorMark2 = PixelSearch(1852, 158, 1910, 375, 0x0D9DC0 , 0);rechts
	$PixelPosColorMark3 = PixelSearch(1660, 319, 1910, 375, 0x0D9DC0 , 0);unten
	$PixelPosColorMark4 = PixelSearch(1722, 214, 1837, 325, 0x63D5FC , 0);mitte

Do

Select
	Case		IsArray($PixelPosColorMark0)
	MouseClick("left", $PixelPosColorMark0[0], $PixelPosColorMark0[1], 1, 0)
	Sleep(3000)


	Case		IsArray($PixelPosColorMark1)
	MouseClick("left", $PixelPosColorMark1[0], $PixelPosColorMark1[1], 1, 0)
	Sleep(3000)


	Case		IsArray($PixelPosColorMark2)
	MouseClick("left", $PixelPosColorMark2[0], $PixelPosColorMark2[1], 1, 0)
	Sleep(3000)


	Case		IsArray($PixelPosColorMark3)
	MouseClick("left", $PixelPosColorMark3[0], $PixelPosColorMark3[1], 1, 0)
	Sleep(3000)



	Case		IsArray($PixelPosColorMark4)
	MouseClick("left", $PixelPosColorMark4[0], $PixelPosColorMark4[1], 1, 0)
	Sleep(7500)
	Start4()


	Case	 Else
	Send("{Left down}")
	Sleep(100)
	Send("{Left up}")
	Sleep(100)

EndSelect

Until IsArray($PixelPosColorMark4)
EndFunc
:confused:
02/16/2015 20:22 alpines#10
Wie findet man raus ob man rekursiv programmiert hat? Geh dein Script per Hand durch, wenn du aus _1() in jedem Fall _2() callest und in _2() in jedem Fall _1() callest ist das rekursiv.
02/16/2015 21:54 warfley#11
Quote:
Originally Posted by RF1T2 View Post
Ist der Gedanke hierbei so ok?

Code:
Func _array1()
	$PixelPosColor0 = PixelSearch(38 ,119 , 1615, 872, 0x412F4E, 1)

Select

   Case	IsArray($PixelPosColor0)
   MouseClick("left", $PixelPosColor0[0], $PixelPosColor0[1], 1, 0)
   Sleep(3000)
Start2()

   Case	Else
		Do
			Send("{Left down}")
			Sleep(200)
			Send("{Left up}")
			Sleep(500)
		Until IsArray($PixelPosColor0)
		_array1()

EndSelect
EndFunc
Es scheint nie bis _array1() zu kommen aber hilft das ausreichend gegen Rekursion?
WTF? Das ist falsch auf allen möglichen ebenen
hier ist das mal sauber in Pseudo und normalen Tab abständen
Code:
Funktion Foo
  PixelPosColor0 := PixelSearch(38 ,119 , 1615, 872, 0x412F4E, 1)  //Startwert für die erste Überprüfung
  While not IsArray(PixelPosColor0)  //Kopfzeilige Schleife damit von Anfang an überprüft wird, und es keinen Ersten mindestdurchlauf gibt
    Send("{Left down}")
    Sleep(200)
    Send("{Left up}")
    Sleep(500)
    PixelPosColor0 := PixelSearch(38 ,119 , 1615, 872, 0x412F4E, 1) //Neuen wert für nächste Überprüfung
  // richtiger wert gefunden, geht weiter
  MouseClick("left", $PixelPosColor0[0], $PixelPosColor0[1], 1, 0)  
  Sleep(3000)
Am besten ein Tipp, lösche mal deine Funktionen, denke drüber nach was du tuen willst, wie du es am besten Umsetzen könntest (male dir zur Not ein Diagramm) und fange nochmal von Vorn an


PS: und benutze mal bitte ordentliche Namen für deine Funktionen, jede Funktion soll ja was bestimmtes machen, benenne sie dann auch so (z.B. KlickeAufDenKopfVonDemTypenInDerMitteDesBildesFunk tion ist ein besserer Name als array1)

Und noch ein Tipp, verwende Rekrusionen nur wie Snow geschrieben hat,
Wenn Startwert dann gebe Startergebnis zurück, wenn nicht dann mache was rufe die funktion mit neuen Parametern erneut auf, so dass du auf jeden fall auf den Startwert kommst

Eine Funktion muss immer nach einer (beliebigen) endlichen anzahl an durchlaufen Terminieren.

PPS: Hier mal ein kurzer auszug aus wikipedia zur Definition eines Algorithmus:
Quote:
Aus dieser Definition sind folgende Eigenschaften eines Algorithmus ableitbar:

1. Das Verfahren muss in einem endlichen Text eindeutig beschreibbar sein (Finitheit).
2. Jeder Schritt des Verfahrens muss tatsächlich ausführbar sein (Ausführbarkeit).
3. Das Verfahren darf zu jedem Zeitpunkt nur endlich viel Speicherplatz benötigen (Dynamische Finitheit, siehe Platzkomplexität).
4. Das Verfahren darf nur endlich viele Schritte benötigen (Terminierung, siehe auch Zeitkomplexität).

Darüber hinaus wird der Begriff Algorithmus in praktischen Bereichen oft auf die folgenden Eigenschaften eingeschränkt:

1. Der Algorithmus muss bei denselben Voraussetzungen das gleiche Ergebnis liefern (Determiniertheit).
2. Die nächste anzuwendende Regel im Verfahren ist zu jedem Zeitpunkt eindeutig definiert (Determinismus).