Die Kollisionsberechnung für 1000 Rechtecke geht in konstanter Zeit und dauert genausolang wie die Kollisionserkenung von einem einzigen Rechteck. Nimm eine Bitmap in Spielfeldgröße mit der Farbe 0x00000000, anschließend nummerierst du alle Rechtecke mit 0x00000001, usw usw und zeichnest diese in die Bitmap. Dann kann man per Pixelgetcolor (oder per Dllstruct, wenn man es schnell haben will) innerhalb weniger Takte wissen ob in der Nähe des Balls ein Rechteck ist. Anschließend überprüft man die Vektorkollision (Also die Rechnung für die Bewegung des Balls) nur mit den Rechtecken die in der direkten Umgebung des Balls sind (sollten immer unter 8 Stück sein, sonst wirds unlogisch :D).
Beiträge von Mars
-
-
Das mit den Strahlen hatte ich irgendwo schonmal ausprobiert. Wenn ich mich nicht irre haben 3 Strahlen ausgereicht, nämlich in Flugrichtung mit den Startpunkten Senkrecht links, senkrecht rechts am Kreis und einer in der Mitte. Da man via Vektorrechnung und ohne "feste" Schritte Arbeitet überprüft man nur ob die Strecken (Bewegungsvektoren) andere Strecken schneiden, und das tun sie unabhängig von der Objektgröße.
Das Vorgehen bei "korrekter" Kollision ist wie folgt: ("Zeit zwischen den Frames" = T = 1)
- Man hat z.B. 10 Kugeln.
- Man überprüft ob es im nächsten Frame überhaupt irgendeine Kollision gibt. Wenn nein -> bewegen, fertig. Wenn ja gehts weiter.
- Man findet die zeitlich gesehen erste Kollision (zum Zeitpunkt t < T) und berechnet diese. Man bewegt alle Kugeln um ihrem Richtungsvektor mit Faktor dt/T.
- Man führt den vorherigen Schritt solange aus, bis die zeitlich gesehen nächste Kollision bei einem t > T stattfindet. Dann bewegt man die Kugeln noch das kleine Stück (im Normalfall der Faktor 1 - t) bis T voll ist, und hat den zu berechnenden Frame fertig.Edit: Das ist hier nur die Weganleitung, wie man die Kollisionen im Konkreten berechnet kann man woanderst nachlesen
-
Mir graut es bei dieser Vorstellung
AutoIt
Alles anzeigenFunc SortN(ByRef $a) Local $t Switch UBound($a) Case 2 If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf Case 3 If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[1] $a[1] = $a[2] $a[2] = $t EndIf If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf Case 4 If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[1] $a[1] = $a[2] $a[2] = $t EndIf If $a[2] < $a[3] Then $t = $a[3] $a[3] = $a[2] $a[2] = $t EndIf If $a[1] < $a[2] Then $t = $a[1] $a[1] = $a[2] $a[2] = $t EndIf If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[1] $a[1] = $a[2] $a[2] = $t EndIf Case 5 If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[3] < $a[4] Then $t = $a[4] $a[4] = $a[3] $a[3] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf Case 6 If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[3] < $a[4] Then $t = $a[4] $a[4] = $a[3] $a[3] = $t EndIf If $a[4] < $a[5] Then $t = $a[5] $a[5] = $a[4] $a[4] = $t EndIf If $a[3] < $a[4] Then $t = $a[4] $a[4] = $a[3] $a[3] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[0] < $a[1] Then $t = $a[0] $a[0] = $a[1] $a[1] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[3] < $a[4] Then $t = $a[4] $a[4] = $a[3] $a[3] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf If $a[1] < $a[2] Then $t = $a[2] $a[2] = $a[1] $a[1] = $t EndIf If $a[2] < $a[3] Then $t = $a[2] $a[2] = $a[3] $a[3] = $t EndIf EndSwitch EndFunc ;==>SortN
AutoIt
Alles anzeigen#include <Array.au3> Global Const $N = 50000 Global $f_DecimalPlaces = 5 Global $iT, $f_Overhead, $a_Results[0][3] Global $a_Array[5] ; determine the overhead of loop [and optional other stuff] $iT = TimerInit() For $i = 1 To $N For $j = 0 To 4 $a_Array[$j] = Random(1, 100, 1) Next Next $f_Overhead = TimerDiff($iT) ; the first measurement ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "_5Sort" $iT = TimerInit() For $i = 1 To $N For $j = 0 To 4 $a_Array[$j] = Random(1, 100, 1) Next _5Sort($a_Array[0], $a_Array[1], $a_Array[2], $a_Array[3], $a_Array[4]) Next $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N ; the first measurement ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "____5Sort" $iT = TimerInit() For $i = 1 To $N For $j = 0 To 4 $a_Array[$j] = Random(1, 100, 1) Next ____5Sort($a_Array[0], $a_Array[1], $a_Array[2], $a_Array[3], $a_Array[4]) Next $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N ; the second measurement ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "__5Sort" $iT = TimerInit() For $i = 1 To $N For $j = 0 To 4 $a_Array[$j] = Random(1, 100, 1) Next __5Sort($a_Array) Next $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N ; the third measurement ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "___5Sort" $iT = TimerInit() For $i = 1 To $N For $j = 0 To 4 $a_Array[$j] = Random(1, 100, 1) Next ___5Sort($a_Array) Next $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N ; the fourth measurement ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "ISort" $iT = TimerInit() For $i = 1 To $N For $j = 0 To 4 $a_Array[$j] = Random(1, 100, 1) Next _ISort($a_Array) Next $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT - $f_Overhead) / $N ; calculate results and print them out _ArraySort($a_Results, 0, 0, 0, 1) For $i = 0 To UBound($a_Results) - 1 $a_Results[$i][2] = Round($a_Results[$i][1] / $a_Results[0][1], 2) $a_Results[$i][1] = Round($a_Results[$i][1], $f_DecimalPlaces) Next _ArrayDisplay($a_Results, "Measurement Results", "", 16 + 64, Default, "name|time [ms]|factor") Func _ISort(ByRef $A) Local $t1, $t2 For $i = 1 To UBound($A) - 1 $t1 = $A[$i] For $j = $i - 1 To 0 Step -1 $t2 = $A[$j] If $t1 > $t2 Then ExitLoop $A[$j + 1] = $t2 Next $A[$j + 1] = $t1 Next EndFunc ;==>_ISort Func ___5Sort(ByRef $A) ; Die ganz einfache Version Local $t If $A[0] > $A[1] Then $t = $A[0] $A[0] = $A[1] $A[1] = $t EndIf If $A[1] > $A[2] Then $t = $A[2] $A[2] = $A[1] $A[1] = $t EndIf If $A[2] > $A[3] Then $t = $A[2] $A[2] = $A[3] $A[3] = $t EndIf If $A[3] > $A[4] Then $t = $A[4] $A[4] = $A[3] $A[3] = $t EndIf If $A[2] > $A[3] Then $t = $A[2] $A[2] = $A[3] $A[3] = $t EndIf If $A[1] > $A[2] Then $t = $A[2] $A[2] = $A[1] $A[1] = $t EndIf If $A[0] > $A[1] Then $t = $A[0] $A[0] = $A[1] $A[1] = $t EndIf If $A[1] > $A[2] Then $t = $A[2] $A[2] = $A[1] $A[1] = $t EndIf If $A[2] > $A[3] Then $t = $A[2] $A[2] = $A[3] $A[3] = $t EndIf If $A[1] > $A[2] Then $t = $A[2] $A[2] = $A[1] $A[1] = $t EndIf EndFunc Func ____5Sort(ByRef $1, ByRef $2, ByRef $3, ByRef $4, ByRef $5) ; Die ganz einfache Version Local $t If $1 > $2 Then $t = $1 $1 = $2 $2 = $t EndIf If $2 > $3 Then $t = $3 $3 = $2 $2 = $t EndIf If $3 > $4 Then $t = $3 $3 = $4 $4 = $t EndIf If $4 > $5 Then $t = $5 $5 = $4 $4 = $t EndIf If $3 > $4 Then $t = $3 $3 = $4 $4 = $t EndIf If $2 > $3 Then $t = $3 $3 = $2 $2 = $t EndIf If $1 > $2 Then $t = $1 $1 = $2 $2 = $t EndIf If $2 > $3 Then $t = $3 $3 = $2 $2 = $t EndIf If $3 > $4 Then $t = $3 $3 = $4 $4 = $t EndIf If $2 > $3 Then $t = $3 $3 = $2 $2 = $t EndIf EndFunc ;~ Global $B[] = [3, 1, 2, 5, 4] ;~ __5Sort($B) ;~ _ArrayDisplay($B) Func __5Sort(ByRef $A) Local $t If $A[0] < $A[1] Then ; if a < b: a, b = b, a $t = $A[1] $A[1] = $A[0] $A[0] = $t EndIf If $A[2] < $A[3] Then ; if c < d: c, d = d, c $t = $A[2] $A[2] = $A[3] $A[3] = $t EndIf If $A[0] < $A[2] Then ; if a < c: a, b, c, d = c, d, a, b $t = $A[2] $A[2] = $A[0] $A[0] = $t $t = $A[3] $A[3] = $A[1] $A[1] = $t EndIf If $A[4] < $A[2] Then ;~ if e < c: If $A[4] > $A[3] Then ; if e > d: d, e = e, d $t = $A[3] $A[3] = $A[4] $A[4] = $t EndIf ElseIf $A[4] < $A[0] Then ; if e < a: c, d, e = e, c, d $t = $A[2] $A[2] = $A[4] $A[4] = $A[3] $A[3] = $t Else ;~ else: a, c, d, e = e, a, c, d $t = $A[0] $A[0] = $A[4] $A[4] = $A[3] $A[3] = $A[2] $A[2] = $t EndIf If $A[1] < $A[3] Then ; if b < d: If $A[1] < $A[4] Then ; if b < e: return b, e, d, c, a Local $B[5] = [$A[1], $A[4], $A[3], $A[2], $A[0]] $A = $B Else ; else: return e, b, d, c, a Local $B[5] = [$A[4], $A[1], $A[3], $A[2], $A[0]] $A = $B EndIf Else If $A[1] < $A[2] Then ; if b < c: return e, d, b, c, a Local $B[5] = [$A[4], $A[3], $A[1], $A[2], $A[0]] $A = $B Else ; else: return e, d, c, b, a Local $B[5] = [$A[4], $A[3], $A[2], $A[1], $A[0]] $A = $B EndIf EndIf EndFunc ;==>_5Sort ;~ Global $X[] = [5, 3, 4, 2, 1] ;~ _5Sort($X[0], $X[1], $X[2], $X[3], $X[4]) ;~ _ArrayDisplay($X) Func _5Sort(ByRef $A, ByRef $B, ByRef $C, ByRef $D, ByRef $E) Local $t If $A < $B Then ; if a < b: a, b = b, a $t = $B $B = $A $A = $t EndIf If $C < $D Then ; if c < d: c, d = d, c $t = $C $C = $D $D = $t EndIf If $A < $C Then ; if a < c: a, b, c, d = c, d, a, b $t = $C $C = $A $A = $t $t = $D $D = $B $B = $t EndIf If $E < $C Then ;~ if e < c: If $E > $D Then ; if e > d: d, e = e, d $t = $D $D = $E $E = $t EndIf ElseIf $E < $A Then ; if e < a: c, d, e = e, c, d $t = $C $C = $E $E = $D $D = $t Else ;~ else: a, c, d, e = e, a, c, d $t = $A $A = $E $E = $D $D = $C $C = $t EndIf If $B < $D Then ; if b < d: If $B < $E Then ; if b < e: return b, e, d, c, a $t = $A $A = $B $B = $E $E = $t $t = $C $C = $D $D = $t Else ; else: return e, b, d, c, a $t = $A $A = $E $E = $t $t = $C $C = $D $D = $t EndIf Else If $B < $C Then ; if b < c: return e, d, b, c, a $t = $A $A = $E $E = $t $t = $B $B = $D $D = $C $C = $t Else ; else: return e, d, c, b, a $t= $A $A = $E $E = $t $t = $B $B = $D $D = $t EndIf EndIf EndFunc ;==>_5Sort
lg
M -
Ich schaffe es einfach nicht deine Methode zu überbieten...
Hab jetzt folgendes ausprobiert: Das Gesamtarray in Teilarrays (Größe 5) spalten (im Übertragenen Sinn. In Wirklichkeit gibts nur eine Neuanordnung), diese mit Swapsort (Weil man den für kleine Arrays gut hardcoden kann, sodass man keine Schleifen oder ähnliches hat) sortieren, anschließend nicht in 1er Schritten durch das Array laufen, sondern in 5er Schritten (Wenn man hinten angekommen ist wieder von Vorne starten und ein element versetzt weitermachen).
Resultat:
- in den ersten n/5 der Elementen hat man jeweils die größten Elemente aus den 5er Teilarrays.
- in den zweiten n/5 Elementen hat man jeweils die 2t größten Elemente aus den 5er Teilarrays... usw
Anschließend kann man eine meiner beiden Alten Methoden (Mars03 und Mars04) über das teilweise vorsortierte Array laufen lassen, die nun wesentlich schneller zum Ergebnis kommen. Insgesamt ist die Sache zwar schneller als meine bisherigen Versuche, aber wesentlich langsamer als die Post17 Methode. Hab aber noch ein paar Ideen auf lager, mal schauen ob da noch was geht^^ -
AspirinJunkie:
Die spezielle Methode ist eine Ecke schneller, aber aus Gründen die ich nicht genau finden konnte tauchen im unteren Bereich ab und zu falsche Zahlen auf. Habe ein (hoffentlich möglichst kleines) Beispielskript dazu gebastelt das die Unterschiede zu Quicksort zeigt. Der Fehler tritt nicht immer auf, daher muss das Beispielskript ggf. mehrfach gestartet werden damit andere Zufallszahlen genutzt werden.AutoIt
Alles anzeigen#include <Array.au3> For $i = 0 To 9 Step 1 Test() Next Func Test() Local $sDump = '' Local $a = RandomNumbers(10) Local $QS = __Quicksort($a, 5) Local $AS = _ArrayGetNBiggestElements($a, 5) For $i = 0 To UBound($QS) - 1 Step 1 If $QS[$i] <> $AS[$i] Then $sDump &= Hex($i, 8) & '|' Next If $sDump Then $sDump = StringTrimRight($sDump, 1) If $sDump Then ConsoleWrite(@CRLF & ' Array[' & StringFormat('%3d', UBound($a)) & ']' & @CRLF) For $i = 0 To UBound($a) - 1 Step 1 ConsoleWrite('! ' & StringFormat('%.17f', $a[$i]) & @CRLF) Next ConsoleWrite(@CRLF & ' Quicksort[' & StringFormat('%3d', UBound($QS)) & '] | Aspirin02[' & StringFormat('%3d', UBound($AS)) & ']' & @CRLF) For $i = 0 To UBound($QS) - 1 Step 1 ConsoleWrite((StringInStr($sDump, Hex($i, 8), 0, 1) ? '! ' : '+ ') & StringFormat('%.17f', $QS[$i]) & ' | ' & StringFormat('%.17f', $AS[$i]) & @CRLF) Next ConsoleWrite(@CRLF) Exit EndIf EndFunc ;==>Test ;~ Global $a_Array[] = [2, 6, 8, 1, 1, 5, 8, 9, 31, 41, 163, 13, 67, 12, 74, 17, 646, 16, 74, 12, 35, 98, 12, 43] ;~ Global $N = 5 ;~ $a_Biggest = _ArrayGetNBiggestElements($a_Array, $N) ;~ _ArrayDisplay($a_Biggest, "Die " & $N & " größten Elemente im Array") Func _ArrayGetNBiggestElements($a_A, $d_Nth = 1) ; by AspirinJunkie Local $i_Min = 0, $i_Max = UBound($a_A) - 1 If $d_Nth = $i_Max + 1 Then _ArraySort($a_A, 1) Return $a_A EndIf Do Local $iMiddle = Floor(($i_Max + $i_Min) / 2) Local $a = $a_A[$i_Min], $b = $a_A[$i_Max], $c = $a_A[$iMiddle] ; calculate the pivot element by median(Array[min], Array[middle], Array[max]) Local $p_Value = $a > $b ? $a > $c ? $c > $b ? $c : $b : $a : $a > $c ? $a : $c > $b ? $b : $c ; = Median(a,b,c) Local $p_Index = $p_Value = $a ? $i_Min : $p_Value = $b ? $i_Max : $iMiddle ; = Index(p_Value) ; move the pivot-element to the end of the array If $p_Index < $i_Max Then $a_A[$p_Index] = $a_A[$i_Max] $a_A[$i_Max] = $p_Value EndIf ; Partition with Hoare's algorithm: Local $i = $i_Min - 1 Local $j = $i_Max + 1 Local $t Do ; start from right and go left until the next element which is smaller than pivot: Do $j -= 1 Until $a_A[$j] > $p_Value Or $j = $i_Min ; start from left and go right until the next element which is greater than pivot: Do $i += 1 Until $a_A[$i] < $p_Value Or $i = $i_Max ; swap if elements are on the wrong side of the lists If $i < $j Then $t = $a_A[$j] $a_A[$j] = $a_A[$i] $a_A[$i] = $t EndIf Until $i >= $j ; swap with pivot-element if pivot is at the wrong list-side: If $a_A[$i] > $p_Value Then $a_A[$i_Max] = $a_A[$i] $a_A[$i] = $p_Value EndIf If $i = $d_Nth Then If $d_Nth > 16 Then _ArraySort($a_A, 1, 0, $d_Nth) Else ; sort with insertion sort (faster than Quicksort for small element count) For $i = 1 To $d_Nth $t1 = $a_A[$i] For $j = $i - 1 To 0 Step -1 $t2 = $a_A[$j] If $t1 < $t2 Then ExitLoop $a_A[$j + 1] = $t2 Next $a_A[$j + 1] = $t1 Next EndIf ReDim $a_A[$d_Nth] Return $a_A ElseIf $i > $d_Nth Then $i_Max = $i - 1 Else $i_Min = $i + 1 EndIf Until 0 EndFunc ;==>_ArrayGetNBiggestElements Func RandomNumbers($iCnt = 1) Local $aArray[$iCnt] For $i = 0 To $iCnt - 1 Step 1 $aArray[$i] = Random() Next Return $aArray EndFunc ;==>RandomNumbers Func __Quicksort($aArray, $iSubSetSize = 1) _ArraySort($aArray, 1) ; Rocket Science ReDim $aArray[$iSubSetSize] ; Oberen Teil abschneiden, fertig. Return $aArray EndFunc ;==>__Quicksort
lg
M -
Interessant ist die Sache auf jeden Fall, aber ich glaube nicht, dass das eine Person in einem anständigen Zeitraum alleine programmieren kann.
-
Damit hast du eine Waffe ins Feld geschickt, die so schnell keiner besiegen wird
Villeicht gibt es ja doch eine Funktion die "überall" optimal läuft und nicht nur für bestimmte Fälle.Vielen Dank, den Startpost aktualisiere ich gleich.
Da sieht man mal was alles möglich ist, die Zaubershow ist aber noch nicht vorbei, jetzt wird es erst richtig spannend
lg
M -
Also ich hab nicht nur fleißig geredet, sondern auch schon 2 Methoden zur Lösung gebastelt (Die erste zähle ich mal nicht, denn Quicksort + ReDim ist kein Denkaufwand gewesen^^).
Xor, du bist am Zug
-
O(n*log(k)) ist drin. Dann wäre der Grenzfall für k -> n = O(n*log(n)) was zufälligerweise genau mit Quicksort zusammenfällt. (Und auch exakt die gleiche Funktionalität wie QS bietet. Aus einer unsortierten Liste eine absteigend/aufsteigend sortierte Liste machen)
-
Moin,
Nachdem ich nicht in der Lage war mich in der SB richtig auszudrücken (Deutsche Sprache schwäre Sprache) hier nochmal. (Danke an Xori für seine Geduld mit Personen die so viel verstehen wie ein Ziegelstein :D)
Problemstellung:
Es gibt ein Array mit n Elementen welches Zufallszahlen enthält (oder irgendwelche anderen Zahlen, ist im Prinzip egal).
Aus diesem Array hätte man gerne in möglichst geringer Zeit eine Liste mit den k größten Einträgen in absteigender Reihenfolge. (Also wie z.B. ArrayMax eine "Liste" mit dem größten Eintrag liefert, möchte man eine Liste mit dem größten, dem 2t größten, ... dem k-t größten)Dazu kommt man spontan auf die brilliante Idee: Nimm Quicksort und trenne anschließend den oberen Teil des Arrays ab.
Richtig, genauso kann man es machen. Und wenn man aus einem n = 100 Array die größten 90 Elemente in einer sortierten Rückgabeliste haben will ist das sicherlich der beste Weg. Falls man aus den 100 Elementen aber nur die 5 größten haben will ist es sinnlos das komplette Array zu sortieren.Es gibt schon ein paar Lösungen, die aber bestimmt noch nicht perfekt sind. Gesucht ist die schnellste Methode
Was ist schnell ?
Das ist eine gute Frage. Da es 2 Parameter gibt (n = Arraygröße, k = Anzahl der gesuchten Elemente) ist es unwahrscheinlich, dass eine einzige Funktion auf dem kompletten Spektrum von n und k überall am schnellsten zum Ziel kommt. Wie oben angedeutet kann man QuickSort nicht einfach schlagen, wenn man z.B. von 100 Elementen 90 haben will. Gebraucht werden also funktionen die für Spezialfälle ein besonderst gutes Ergebnis liefern. (z.B. für kleines n, für großes n, für kleines k, für großes k, für k = Wurzel(n), usw usw). Aus diesen Fällen lässt sich im Endeffekt eine Funktion die an vielen Stellen halbwegs optimal läuft zusammenschustern.Anbei 2 kleine Testskripte:
AutoIt: Eigene Funktion einfügen und schauen ob das Ergebnis stimmt
Alles anzeigen#include <Array.au3> Global $a = RandomNumbers(15) Global $m1 = __ArrayMax2($a, 9) Global $m2 = __ArrayMax2($a, 9) Global $m3 = __ArrayMax4($a, 9) ConsoleWrite(@CRLF & 'Array: [' & UBound($a) & ']' & @CRLF) For $i = 0 To UBound($a) - 1 Step 1 ConsoleWrite($a[$i] & ' ') Next ConsoleWrite(@CRLF & @CRLF & '__ArrayMax1: [' & UBound($m1) & ']' & @CRLF) For $i = 0 To UBound($m1) - 1 Step 1 ConsoleWrite($m1[$i] & ' ') Next ConsoleWrite(@CRLF & @CRLF & '__ArrayMax2: [' & UBound($m2) & ']' & @CRLF) For $i = 0 To UBound($m2) - 1 Step 1 ConsoleWrite($m2[$i] & ' ') Next ConsoleWrite(@CRLF & @CRLF & '__ArrayMax4: [' & UBound($m3) & ']' & @CRLF) For $i = 0 To UBound($m3) - 1 Step 1 ConsoleWrite($m3[$i] & ' ') Next ConsoleWrite(@CRLF & @CRLF) Func Find(ByRef $aArray, $nValue) ; Findet den Index für ein sortiertes Array Local $l = 0, $r = UBound($aArray) - 1, $m = Int(($l + $r) / 2) While 1 If $r - $l = 1 Then Return $r If $aArray[$m] > $nValue Then $l = $m Else $r = $m EndIf $m = Int(($l + $r) / 2) WEnd EndFunc ;==>Find Func __ArrayMax4($aArray, $iSubSetSize = 1) $iSubSetSize += 1 ; Ein intern teilweise mit Startindex 1 gearbeitet wird. Local $aRet[$iSubSetSize], $l, $r, $m, $v For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen For $e = $iSubSetSize - 1 To 0 Step -1 ; Jedes Element mit der Resultatliste vergleichen. If $aArray[$i] < $aRet[$e] Then ExitLoop ; Falls es kleiner ist als das kleinste Teil der Resultatliste passiert nichts. $v = $aArray[$i] ; Suchmethode die in einer sortierten Liste deutlich schneller ist, als jedes Element einzeln zu überprüfen. $l = 0 $r = $iSubSetSize - 1 $m = Int(($l + $r) / 2) While 1 If $r - $l = 1 Then ExitLoop ; in $r ist der gesuchte Index If $aRet[$m] > $v Then $l = $m Else $r = $m EndIf $m = Int(($l + $r) / 2) WEnd For $q = $iSubSetSize - 2 To $r - 1 Step -1 ; Rückwärtslaufen um Platz zu machen $aRet[$q + 1] = $aRet[$q] ; Verschieben in linearer Laufzeit. Das ist schlecht, in einem Tree wäre die Sache angenehmer, kommt beim nächsten Mal. Next $aRet[$r] = $aArray[$i] ; Positionieren ExitLoop ; Läuft Next Next For $i = 0 To $iSubSetSize - 2 Step 1 ; Weil intern teilweise mit Startindex 1 gearbeitet wird. $aRet[$i] = $aRet[$i + 1] Next ReDim $aRet[$iSubSetSize - 1] Return $aRet EndFunc Func __ArrayMax2($aArray, $iSubSetSize = 1) Local $aRet[$iSubSetSize] ; Resultatarray erstellen For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen For $e = 0 To $iSubSetSize - 1 Step 1 ; Jedes Element mit der Resultatliste vergleichen. If $aArray[$i] >= $aRet[$e] Then ; Dabei wird zuerst das größte, dann das 2te usw verglichen. For $o = $iSubSetSize - 2 To $e Step -1 ; Falls was gefunden wurde: Resultatliste um 1 nach unten verschieben. $aRet[$o + 1] = $aRet[$o] ; Rückwärtslaufen nicht vergessen, sonst knackts im Gebälk. Next $aRet[$e] = $aArray[$i] ; Der freigewordene Platz bekommt nun das neue größte Element. ExitLoop ; Fertig. Jeder Treffer wird nur 1x eingespeichert. EndIf ; Hier wird gezaubert, die Resultatliste ist zu jeder Zeit vollständig sortiert. Next Next Return $aRet EndFunc ;==>__ArrayMax2 Func __ArrayMax1($aArray, $iSubSetSize = 1) _ArraySort($aArray, 1) ; Rocket Science ReDim $aArray[$iSubSetSize] ; Obersten Teil abschneiden, fertig. Return $aArray EndFunc ;==>__ArrayMax1 Func RandomNumbers($iCnt = 1) Local $aArray[$iCnt] For $i = 0 To $iCnt - 1 Step 1 $aArray[$i] = Random(100, 999, 1) Next Return $aArray EndFunc ;==>RandomNumbers
AutoIt: Wenn die Funktion läuft hier einbauen und gegen die anderen antreten lassen
Alles anzeigen#include <Array.au3> Global $bErrCheck = False ; Nur für "kleine" Runden einschalten, sonst wird die Konsole überflutet falls Fehler auftreten. Global $iSmooth = 0 ; Nur falls man die Ergebnisse Plotten will und keine Lust hat so viele Versuche zu machen bis die Kurve halbwegs glatt ist. ;~ Func Test($iStart = 10, $iEnd = 15, $iSubSetSize = 3, $iVersuche = 25) Global $aTest = Test(50, 100, 20, 1) For $x = 0 To UBound($aTest) - 1 Step 1 For $y = 0 To UBound($aTest, 2) - 1 Step 1 $aTest[$x][$y] = StringReplace($aTest[$x][$y], '.', ',', 0, 1) Next Next _ArrayDisplay($aTest, '', '', 0, @TAB) Func Runde($iArraySize = 100, $iSubSetSize = 5, $iVersuche = 25) ; $iArraySize - Größe des zu untersuchenden Arrays ; $iSubSetSize - Anzahl der gesuchten Werte ; $iVersuche - Anzahl durchgänge aus denen der Mittelwert gebildet wird (um die Laufzeit besser analysieren zu können) ; Runde() lässt die Funktionen einige Male mit gleichen Einstellungen laufen. ; Return - Array mit der Durchschnittlichen Zeit in Millisekunden für jede Funktion. Local $aTime[4][2] ; Beim Hinzufügen die Arraygröße anpassen. $aTime[0][0] = 'Mars 01' ; Arraysort + Redim... easy $aTime[1][0] = 'Platzhalter' $aTime[2][0] = 'Mars 03' $aTime[3][0] = 'Mars 04' Local $aResult[UBound($aTime)], $aCheck, $t, $s, $aTest For $i = 1 To $iVersuche Step 1 $aTest = RandomNumbers($iArraySize) ; Die Funktionen dürfen das Originalarray nicht verändern. Daher muss es nur 1x erzeugt werden. Switch Random(0, 1, 1) ; Da man nie weiß was AutoIt intern betreibt kann es sein, dass Funktionen standardmäßig je nach Position im Code Case 0 ; schneller oder langsamer laufen. Daher ist an dieser Stelle ein Switch um die Reihenfolgen durchzumischen. $t = TimerInit() $aResult[0] = __Mars01($aTest, $iSubSetSize) $aTime[0][1] += TimerDiff($t) $t = TimerInit() $aResult[1] = Platzhalter($aTest, $iSubSetSize) $aTime[1][1] += TimerDiff($t) $t = TimerInit() $aResult[2] = __Mars03($aTest, $iSubSetSize) $aTime[2][1] += TimerDiff($t) $t = TimerInit() $aResult[3] = __Mars04($aTest, $iSubSetSize) $aTime[3][1] += TimerDiff($t) Case 1 $t = TimerInit() $aResult[3] = __Mars04($aTest, $iSubSetSize) $aTime[3][1] += TimerDiff($t) $t = TimerInit() $aResult[2] = __Mars03($aTest, $iSubSetSize) $aTime[2][1] += TimerDiff($t) $t = TimerInit() $aResult[1] = Platzhalter($aTest, $iSubSetSize) $aTime[1][1] += TimerDiff($t) $t = TimerInit() $aResult[0] = __Mars01($aTest, $iSubSetSize) $aTime[0][1] += TimerDiff($t) EndSwitch ; Überprüfen ob alle das gleiche raushaben. If $bErrCheck Then For $e = 0 To UBound($aResult) - 1 Step 1 $aCheck = $aResult[$e] $s = 0 For $o = 0 To UBound($aCheck) - 1 Step 1 $s += $aCheck[$o] Next $aResult[$e] = $s ; $aResult ist nur noch die Summe aller Elemente -> Einfacher zu vergleichen und nahezu genauso aussagekräftig. Next ; Dann wird nicht überprüft ob die Resultatliste Sortiert vorliegt, das ist aber zweitrangig. For $e = 1 To UBound($aResult) - 1 Step 1 ; Wir nehmen mal an, dass Quicksort IMMER richtig liegt (ist immerhin milliardenfach erprobt diese Methode) If $aResult[0] <> $aResult[$e] Then ConsoleWrite('!ERROR: ' & '[' & StringFormat('%5s', $iArraySize) & '|' & StringFormat('%4s', $iSubSetSize) & '] ' & $aTime[$e][0] & (Random(0, 1, 1) ? (Random(0, 1, 1) ? ' hat groben Unfug gebaut.' : ' hat keine Ahnung von Mathe.') : (Random(0, 1, 1) ? ' macht seinen verdammten Job nicht.' : ' steht in der Ecke und weint.')) & @CRLF) Next EndIf Next For $i = 0 To UBound($aTime) - 1 Step 1 $aTime[$i][1] /= $iVersuche Next Return $aTime EndFunc ;==>Runde #Region - Funktionen Func Platzhalter($aArray, $iSubSetSize = 1) ReDim $aArray[$iSubSetSize] ; Obersten Teil abschneiden. Klappt hier nicht weil nicht sortiert wurde. Return $aArray ; Das hier dient nur als Beispiel. EndFunc ;==>Platzhalter Func __Mars04($aArray, $iSubSetSize = 1) $iSubSetSize += 1 ; Weil intern teilweise mit Startindex 1 gearbeitet wird. Local $aRet[$iSubSetSize], $l, $r, $m, $v For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen For $e = $iSubSetSize - 1 To 0 Step -1 ; Jedes Element mit der Resultatliste vergleichen. If $aArray[$i] < $aRet[$e] Then ExitLoop ; Falls es kleiner ist als das kleinste Teil der Resultatliste passiert nichts. $v = $aArray[$i] ; Suchmethode die in einer sortierten Liste deutlich schneller ist, als jedes Element einzeln zu überprüfen. $l = 0 $r = $iSubSetSize - 1 $m = Int(($l + $r) / 2) While 1 If $r - $l = 1 Then ExitLoop ; in $r ist der gesuchte Index If $aRet[$m] > $v Then $l = $m Else $r = $m EndIf $m = Int(($l + $r) / 2) WEnd For $q = $iSubSetSize - 2 To $r - 1 Step -1 ; Rückwärtslaufen um Platz zu machen $aRet[$q + 1] = $aRet[$q] ; Verschieben in linearer Laufzeit. Das ist schlecht, in einem Tree wäre die Sache angenehmer, kommt beim nächsten Mal. Next $aRet[$r] = $aArray[$i] ; Positionieren ExitLoop ; Läuft Next Next For $i = 0 To $iSubSetSize - 2 Step 1 ; Weil intern teilweise mit Startindex 1 gearbeitet wird. $aRet[$i] = $aRet[$i + 1] Next ReDim $aRet[$iSubSetSize - 1] Return $aRet EndFunc ;==>__Mars04 Func __Mars03($aArray, $iSubSetSize = 1) Local $aRet[$iSubSetSize] For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen For $e = $iSubSetSize - 1 To 0 Step -1 ; Jedes Element mit der Resultatliste vergleichen. If $aArray[$i] < $aRet[$e] Then ExitLoop ; Falls es kleiner ist als das kleinste Teil der Resultatliste passiert nichts. For $o = 0 To $iSubSetSize - 1 Step 1 ; Abwandlung von Insertion Sort verwenden If $aArray[$i] >= $aRet[$o] Then ExitLoop ; um in eine Sortierte Liste ein Element einzufügen. Next For $q = $iSubSetSize - 2 To $o Step -1 ; Rückwärtslaufen um Platz zu machen $aRet[$q + 1] = $aRet[$q] Next $aRet[$o] = $aArray[$i] ; Positionieren ExitLoop ; Läuft Next Next Return $aRet EndFunc ;==>__Mars03 Func __Mars02($aArray, $iSubSetSize = 1) Local $aRet[$iSubSetSize] For $i = 0 To UBound($aArray) - 1 Step 1 ; Komplettes Array durchlaufen For $e = 0 To $iSubSetSize - 1 Step 1 ; Jedes Element mit der Resultatliste vergleichen. If $aArray[$i] >= $aRet[$e] Then ; Dabei wird zuerst das größte, dann das 2te usw verglichen. For $o = $iSubSetSize - 2 To $e Step -1 ; Falls was gefunden wurde: Resultatliste um 1 nach unten verschieben. $aRet[$o + 1] = $aRet[$o] ; Rückwärtslaufen nicht vergessen, sonst knackts im Gebälk. Next $aRet[$e] = $aArray[$i] ; Der freigewordene Platz bekommt nun das neue größte Element. ExitLoop ; Fertig. Jeder Treffer wird nur 1x eingespeichert. EndIf ; Hier wird gezaubert, die Resultatliste ist zu jeder Zeit vollständig sortiert. Next Next Return $aRet EndFunc ;==>__Mars02 Func __Mars01($aArray, $iSubSetSize = 1) _ArraySort($aArray, 1) ; Rocket Science ReDim $aArray[$iSubSetSize] ; Obersten Teil abschneiden, fertig. Return $aArray EndFunc ;==>__Mars01 #EndRegion - Funktionen #Region - Unfug Func RandomNumbers($iCnt = 1) Local $aArray[$iCnt] For $i = 0 To $iCnt - 1 Step 1 $aArray[$i] = Random() Next Return $aArray EndFunc ;==>RandomNumbers Func Test($iStart = 10, $iEnd = 15, $iSubSetSize = 3, $iVersuche = 25) ; $iStart - Startwert für die Arraygröße ; $iEnd - Endwert für die Arraygröße ; $iSubSetSize - Schau bei ner anderen Beschreibung, sei fleißig ; $iVersuche - Anzahl Durchgänge um den Mittelwert zu bilden. Local $aRunde = Runde(1, 1, 1) ; Testrunde um das Ergebnisarray bestimmen zu können. Local $aRet[$iEnd - $iStart + 2][UBound($aRunde) + 2] = [['ArraySize', 'SubSetSize']] For $i = 0 To UBound($aRunde) - 1 Step 1 $aRet[0][$i + 2] = $aRunde[$i][0] Next For $v = 1 To $iVersuche Step 1 ; Doch besser die Runden einzeln durchzugeben. For $i = $iStart To $iEnd Step 1 $aRunde = Runde($i, $iSubSetSize, 1) $aRet[$i - $iStart + 1][0] = $i $aRet[$i - $iStart + 1][1] = $iSubSetSize For $e = 0 To UBound($aRunde) - 1 Step 1 $aRet[$i - $iStart + 1][$e + 2] += $aRunde[$e][1] / $iVersuche Next Next Next If $iSmooth Then Local $aSmooth[$iEnd - $iStart + 1] For $n = 2 To UBound($aRet, 2) - 1 Step 1 For $i = 0 To UBound($aSmooth) - 1 Step 1 $aSmooth[$i] = $aRet[$i + 1][$n] Next _ArraySmooth($aSmooth, $iSmooth, False) For $i = 0 To UBound($aSmooth) - 1 Step 1 $aRet[$i + 1][$n] = $aSmooth[$i] Next Next EndIf Return $aRet EndFunc ;==>Test Func _ArraySmooth(ByRef $aArray, $iSmooth = 1, $bFix = False) If Not IsArray($aArray) Then Return SetError(1, 0, 0) If UBound($aArray, 0) <> 1 Then Return SetError(2, 0, 0) If Not IsInt($iSmooth) Or $iSmooth < 1 Or $iSmooth > 1e9 Then Return SetError(3, 0, 0) For $i = 1 To $iSmooth Step 1 $aArray = __ArraySmooth($aArray, $bFix) Next EndFunc ;==>_ArraySmooth Func __ArraySmooth($aArray, $bFix) Local $iUBound = UBound($aArray), $aCopy[$iUBound], $nSum = $bFix ? __ArraySum($aArray, 1, $iUBound - 1) : 0, $nSum2 $aCopy[0] = $bFix ? $aArray[0] : 0.75 * $aArray[0] + 0.25 * $aArray[1] For $i = 1 To $iUBound - 2 Step 1 $aCopy[$i] = 0.25 * $aArray[$i - 1] + 0.5 * $aArray[$i] + 0.25 * $aArray[$i + 1] Next $aCopy[$iUBound - 1] = $bFix ? $aArray[$iUBound - 1] : 0.75 * $aArray[$iUBound - 1] + 0.25 * $aArray[$iUBound - 2] $nSum2 = $bFix ? __ArraySum($aCopy, 1, $iUBound - 1) : 0 If $bFix Then For $i = 1 To $iUBound - 2 Step 1 $aCopy[$i] *= $nSum / $nSum2 Next EndIf Return $aCopy EndFunc ;==>__ArraySmooth Func __ArraySum(ByRef $aArray, $iStart = 0, $iEnd = -1) If $iEnd = -1 Then $iEnd = UBound($aArray) Local $n For $i = $iStart To $iEnd - 1 Step 1 $n += $aArray[$i] Next Return $n EndFunc ;==>__ArraySum #EndRegion - Unfug
Edit1: Mars02 ist rausgeflogen, weil die Funtkion in allen Fällen deutlich schlechter als Mars03 ist. Neu hinzugekommen ist Mars04, die in einigen Fällen (vorallem bei mittlerem k) etwas schneller ist.
Edit2: AspirinJunkie hat eine Funktion beigesteuert die in fast allen Fällen schneller ist, als reines Quicksort. Für die UDF und das Testskript bitte in Post 12 nachschauen.
Da ich ein Diagrammfan bin gibts hier auch ein paar Bildchen (Weniger Millisekunden sind wichtig. Also je niedriger die Kurve ist, desto besser.)
(Peaks in den Diagrammen kommen daher, dass mein Rechner im Hintergrund am Arbeiten ist)
unnamed.pngunnamed2.pngunnamed3.pnglg
M -
Ich kann dir sagen, warum du das machst. GDI+ funktioniert, D2D nicht. (zumindest in AutoIt).
Ich habe viel mit D2D herumprobiert, und es gibt wirklich schöne Sachen die damit möglich sind, die man mit GDI+ direct in die Tonne treten kann. Allerdings funktionieren schon triviale Sachen wie "Lade ein Bild mit Alphakanal aus dem Arbeitsspeicher" nicht einfach so, obwohl es speziell zu diesem Zweck D2D Funktionen gibt. Ich habe Stunden und Tagelang (mit eukalyptus zusammen) herumprobiert, die Funktionen arbeiten in AutoIt nicht so wie sie sollten. Weiterhin ist es schwieriger Fehler zu finden, bei GDI+ gibt es wesentlich weniger "seltsame Einstellungen", Flags, "Versionen eines Elements" usw usw, die einem die Fehlersuche erschweren. Wenn es klemmt schaut man, ob GDI+ Startup aufgerufen wurde, überprüft ein paar Variablen, fertig. Bei D2D kommt es oft vor, dass alles so ist wie es sein sollte und man keine Ahnung hat was hier eigentlich los ist und warum etwas nicht funktioniert.In golang habe ich SDL ausprobiert und muss sagen: Das ist ein schöner Wrapper für D2D (sehr einfach gehalten, tut exakt das was es soll, schmiert nicht oft ab wenn man Fehler macht), ist wahrscheinlich auch in AutoIt wesentlich einfacher zu verwenden als D2D. UDFs in der Richtung gibts soweit ich weiß auch.
lg
M -
-
Irgendwann in der Zukunft... wenn man sich nicht mehr Backsteine mit Spanngurten vor das Gesicht presst, sondern ganz entspannt mit einer Brille bedient wird, die sowohl volltransparent, halbtransparent/holografisch, oder komplett opak arbeiten kann (also sowohl AR als auch VR funktioniert)... Dann gönne ich mir sowas auch, aber vorher nicht
-
Auch wenn das Thema schon gegessen ist muss ich dazu noch was sagen:
Ich habe es schon unzählige Male gehabt, dass Dateien die irgendwas aus meinen Skripten auslagern um von anderen gelesen zu werden Array->Str und dann FileWrite, beim Einlesen nur Unfug herausgeben, obwohl ALLES nur Asc Zeichen waren. Ohne FileOpen mit explizitem Modus mache ich daher überhaupt nichts mehr.lg
M -
Bei Powerpoint ist es eigentlich sinnvoll die Bilder in Originalgröße (außer es sind 20 Megapixel oder sowas) einzufügen, und nur die Anzeige zu skalieren. Dann hat man in der Präsentation auch auf höheren Bildschirmauflösungen ein scharfes Bild.
-
Genau die gleiche Idee ist vor einiger Zeit doch schonmal aufgetaucht. Was wir damals festgestellt hatten (und die ich noch im Kopf habe) waren folgende:
[1] - Native Befehle/Macros (GuiCreate, ConsoleWrite, @DesktopWidth, usw usw) müssten in FB implementiert werden ohne dass wir "hineinschauen" können wie diese Befehle intern funktionieren.
[2] - Die Grammatik (wie oben schon gesagt) muss bekannt sein, damit man von normaler Au3-Syntax zur FB-Syntax wechseln kann.
[3] - UDFs, verschiedene Programmierstile, usw sind vollkommen egal. Vor dem Kompilieren werden sowieso alle Daten in einem einzigen Skript zusammengefasst, das nach Punkt 2 Übersetzbar ist.
[4] - Sollte man den Variant-Typ zuverlässig behandeln wird es große Geschwindigkeitseinbußen geben. (Vor jeder Berechnung prüfen wie die Datentypen sind und ggf. casten)
[5] - DllStructs können wie ein normales Array (mit vorgegebenem Datentyp) verwendet werden, da das in FB Äquivalent gestaltet werden kann, oder umgekehrt. In AutoIt sind normale Arrays aber auf wundersame Weise überall im Speicher verteilt, sodass es keine Arraypointer oder Direktzugriffe gibt.
[6] - Für auftretende Einschränkungen (die es auf jeden Fall geben wird, da man nicht 100% der Sprache einfach so übersetzen kann) muss ein Au3Check ähnliches Skript geschrieben werden um zu überprüfen ob das Skript nach FB übersetzbar ist.Sachen für das Variantproblem waren:
[1] - Alle Variablen eindeutig deklarieren (MustDeclareVars zur Pflicht machen reicht aus, damit implizit alle Datentypen festgelegt sind). Damit kann der Übersetzer an vielen Stellen bereits feststellen wo gecastet werden muss, sodass das Überprüfen zur Laufzeit wegfällt.
[2] - Komplett auf Variant verzichten und in AutoIt manuell "casten" z.B. $a = 5.0, $b = 2. Es wird aus $c = $a + $b ein $c = Int($a) + $b, sodass $c eindeutig ein Integer ist, oder $c = $a + Float($b), sodass $c eindeutig Float ist.
[3] - Funktionen einen eindeutigen Rückgabewert zuweisen. "Func ... Endfunc ; Typ", z.B. "Endfunc ; Int" gibt immer einen Integer zurück. (Kann etwas Arbeit sparen)
[4] - Einen "Behälter" (der jeden Datentyp enthalten kann) für Funktionsparameter benutzen, damit Funktionen nicht überladen werden müssen.Die Liste ist bei weitem nicht vollständig, das sind nur die Sachen die mir direkt zu dem Thema eingefallen sind. Weiterhin weiß ich, dass minx sich auch schonmal an etwas ähnlichem versucht hat (mit seiner selbst gebastelten kompilierbaren Sprache Perseus), wie weit die Entwicklung dort fortgeschritten war weiß ich nicht.
lg
M -
Manche Leute laufen in MMOs die gleiche Instanz 500x nur um ein bestimmtes Item zu bekommen. Ich denke es ist ein menschenmöglicher Aufwand das von Hand zu machen, muss ja nicht alles am gleichen Tag sein.
Was Captchas angeht sind wir hier auch im falschen Forum, ein Program welches Captchas ausfüllen kann wird es hier nicht geben. (siehe Forenregeln)
lg
M -
Für deinen speziellen Fall kann es sein, dass du hier die Antwort findest: Klick Mich.
Allgemein sollten auch in AutoIt keine Methoden explizit implementiert werden müssen. Das Objekt liefert eigentlich alles, was es zum funktionieren braucht. Warum es dennoch nicht immer funktioniert weiß ich leider nicht, da muss ein Objektguru ran.
Edit: Für dein spezielles Beispiel hab ich den Fehler gefunden: Die Methode IndexOf kann mit einem Parameter IndexOf(Objekt, Startposition) verwendet werden. Scheinbar wird die Startposition nicht per Default auf 0 gesetzt, sodass man das manuell machen muss:
AutoIt$AList = ObjCreate("System.Collections.ArrayList") ;////Einträge hinzufügen/////////// $AList.add ("Test1") ; Position 0 $AList.add ("Test6") ; Position 1 $AList.add ("Test4") ; Position 2 $AList.add ("Test2") ; Position 3 $AList.add ("Test3") ; Position 4 $AList.add ("Test5") ; Position 5 ConsoleWrite("indexof: " & $AList.IndexOf("Test4", 0) & @CRLF)
lg
M -
Ich finde es schön, dass sich Jemand mit Jump&Run Spielen in AutoIt beschäftigt. Die Sprache mag nicht für Spiele geeignet sein, diese Hürde lässt sich aber problemlos stämmen. Allerdings ist das vorliegende Spiel bei mir nicht spielbar (es hackt dermaßen stark, dass es kaum Spielbar ist, sieht mir nach Fehlern beim Buffern und Timen aus). Mach das Spiel trotzdem fertig und versuche so viel wie möglich beim Programmieren daraus zu lernen wie man ein Spiel aufbaut. Irgendwann bist du an einem Punkt wo du über deinen alten Code nur noch den Kopf schütteln kannst. Dann ist die Zeit gekommen wo du das gleiche Spielkonzept nochmal von 0 anfängst und es beim 2ten Mal wesentlich besser programmierst. (Das ist der übliche Lernprozess).
Das soll dich jetzt nicht runterziehen und ich meine es nicht Böse. Du bist noch ein Anfänger auf dem Gebiet und da ist es Okay wenn man vieles falsch macht. Bleib dran und wachse an deinen Aufgaben.
lg
M -
Hoi
Edit: Im Forum gibts auch ein paar Tips die bei Spielen weiterhelfen könnten. Ich habe früher auf gerne ein paar kleinigkeiten gebastelt, aber seit ein paar Jahren fehlt mir irgendwie die Lust etwas "großes" anzufangen, und mit etwas kleinem würde ich mich nicht zufrieden geben. Aber eins sei gesagt: AutoIt ist nicht dafür hergestellt um damit Spiele zu programmieren, aber inzwischen kann man via D2D/GDI+ und inlineASM (was sich auch kombinieren lässt) an kritischen Stellen extrem viel herausholen. Falls du etwas planst was auch im Vollbildmodus flüssig laufen soll rate ich dir dringend dazu dich mit D2D auseinanderzusetzen, die Zeichenvorgänge (vorallem Skalierungen, "ins Fenster zeichen", V-Sync, usw) gehen dort wesentlich angenehmer. (via BitBlt kann man zwar auch so sehr gute Zeiten erreichen, dafür fallen aber sehr viele andere Vorteile flach)
Im Anhang habe ich dir mal ein kleines Testskript von mir (ist inzwischen fast 2 Jahre alt... da werde ich schon wieder sentimental^^) angehängt. Da habe ich einige UDFs die zur Spieleentwicklung geeignet sind (wie z.B. Buttons, Hintergründe, Partikel, D2D, ASM, D2D+ASM, usw) ausprobiert, ob das alles so funktioniert wie ich mir das vorstelle. Es ist leider zu 150% unaufgeräumt (da ich keine Lust hatte den alten Kram nochmal komplett auseinanderzunehmen und zu ordnen).
Edit2: Wie man am Änderungsdatum der Dateien sieht musste ich aber trotzdem einiges ändern, damit es überhaupt läuft. Was nicht läuft ist eine schlechte Demo^^
lg
M -
Wird erledigt, Sir. Falls ich jemals Erleuchtung finden sollte (ich glaube nicht daran, aber man weiß ja nie) teile ich sie mit allen