random - no repeat Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

tm6464
Posts: 48
Joined: 17 Jul 2017, 22:56

random - no repeat

21 Mar 2019, 04:03

Hi
ich nutze eine random Funktion die aus einer .txt datei eine Zeile auswählt und diese an eine Variable übergibt
Nun such eich eine Möglichkeit die eine bereits ausgewählte Zeile nicht wiederholt

button1:
loop,10
{
gosub, funktion
sleep, 100000
}
tooltip, end
return


funktion:
MouseClick, left, 947, 667 ;chatklick
loop, 1
{
Random, num, 1, 30
FileReadLine, line, chat1.txt, %num%
sendinput, %line%
sleep, 1000
}
Sleep, 100
send, {enter}
Sleep, 1500
return
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat

21 Mar 2019, 05:18

Moin,

wenn die Datei nicht zu groß ist, würde ich Folgendes vorschlagen:
  1. Datei komplett einlesen, z.B. mit FileRead, DateiInhalt, ....
  2. Eingelesene Datei 'zufällig' sortieren, z.B. Sort, DateiInhalt, Random.
  3. Den zufällig sortierten Inhalt in ein Array übertragen, z.B. ZeilenArray := StrSplit(DateiInhalt, ...).
  4. Bei Bedarf immer die letzte Zeile aus dem Array auslesen und entfernen, z.B. Zeile := ZeilenArray.Pop().
  5. Wenn das ZeilenArray vollständig abgearbeitet ist (ZeilenArray.Length() = 0) ab 2. wiederholen. Alternativ auch ab 1., falls Du den DateiInhalt freigegeben/gelöscht hast
Rohwedder
Posts: 7644
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: random - no repeat

21 Mar 2019, 06:07

Hallo,
diese Randomfunktion gibt statt einem bereits früher gegebenen Wert, "Wiederholung" zurück:

Code: Select all

q::ToolTip,% Random(1,10)

Random(Min,Max)
{
	Static
	Random, Random, Min, Max
	IF Random%Random%
		Return, "Wiederholung"
	Random%Random% := True
	Return, Random
}
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat

22 Mar 2019, 03:52

Hi Rohwedder,

die von Dir eingestellte Funktion scheint mir wenig benutzerfreundlich und verwendet überholte Syntax. Wenn die Funktion prüft, ob der Wert schon einmal erzeugt wurde, sollte sie meiner Meinung nach intern weitersuchen, bis sie einen neuen Wert gefunden hat. Mit dem Rückgabewert Wiederholung lässt sich nichts anfangen. Das führt dann zu Konstrukten wie

Code: Select all

Loop
	R := Random(Min, Max)
Until (R <> "Wiederholung")
Ich finde das nicht prickelnd.

Außerdem kann es bei größeren Wertebereichen nach vielen Aufrufen schon mal dauern, bis die Funktion endlich einen unbenutzten Wert findet.
Rohwedder
Posts: 7644
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: random - no repeat

22 Mar 2019, 11:33

Hallo just me,
Pseudo Arrays werden zwar nicht empfohlen, sind jedoch Ausdruck-Syntax - nicht Altmodisch-Syntax!
Vorteil und Nachteil von Objekt Arrays ist ihre Initialisierung.
Vorteilhaft wenn man es will (auf einen Schlag alle Elemente löschen),
eher von Nachteil, daß man es anfänglich machen muß und es auch ungewollt passieren kann:

Code: Select all

q::
A := [] ;Array A muß initialisiert werden
A[1] := 1
MsgBox,% A[1]
a := 2 ;initialisiert (ungewollt) Array A
MsgBox,% A[1]
Return
Ich finde, Pseudo Arrays und Objekt Arrays haben beide ihre Existenzberechtigung,
ziehe aber erstere vor.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: random - no repeat

22 Mar 2019, 15:59

Deine Pseudo arrays sorgen hier dafür, dass deine Funktion schlechte Optimierung hat und nur einmal verwendet werden kann.
Objekt arrays haben durch die Initialisierung keinen eigenen Nachteil.
Ich sehe ehrlich gesagt keinerlei Grund Pseudo Arrays in AHK zu verwenden.
Für mich haben sie keinerlei Existenzberechtignung.
Recommends AHK Studio
tm6464
Posts: 48
Joined: 17 Jul 2017, 22:56

Re: random - no repeat

22 Mar 2019, 21:32

Danke für die Antworten
@just me kannst du mal ein beispiel zeigen wie der code aussehen soll, besonders punkt 5 verstehe ich nicht

@Rohwedder
thx für deine Mühe, leider bekomme ich bei deinem code immer "Wiederholung" und verstehe zudem überhaupt nicht wie ich das in meine funktion einbauen sollte
Rohwedder
Posts: 7644
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: random - no repeat

23 Mar 2019, 03:09

Hallo,
ich habe die Randomfunktion selbstresetend gemacht.
Sie gibt jetzt solange nicht wiederholende Zufallszahlen zurück bis sie keine mehr findet und stattdessen den Reset meldet.

Code: Select all

q::ToolTip,% Random(1,5)

Random(Min,Max)
{
	Static R
	If R.MaxIndex() = ""
		R := []
	Random, Random, Min, Max
	IF R[Random]
	Loop,% Max-Min
	{		
		If (++Random > Max)
			Random := Min
	}
	Until !R[Random]
	If R[Random]
		Return, "Reset" R := []
	R[Random] := True
	Return, Random
}
Last edited by Rohwedder on 23 Mar 2019, 03:13, edited 1 time in total.
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat

23 Mar 2019, 03:11

Moin,

ich verstehe nicht, welchen Code ich Dir zeigen soll. Die Anweisungen, mit denen man das machen kann, stehen ja schon am Ende der Zeilen der Schritt-für-Schritt-Anleitung.

Zu Pkt. 5 ist muss man sich die Doku zu Object.Pop() ansehen. Die Methode "entfernt das letze Array-Element und gibt es zurück". Daraus folgt, dass das Array nach einer bestimmten Anzahl von Aufrufen leer ist (keine Elemente mehr enthält). Array.Length() liefert dann 0. Wenn man dann noch weitermachen will, muss man das Array neu erstellen. Dazu wäre es gut, wenn das Erstellen des Arrays in eine Funktion oder Subroutine ausgelagert ist, die wiederholt aufgerufen werden kann.

Mit Arrays lassen sich auch alternative Lösungen einfach umsetzen.
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat

23 Mar 2019, 04:44

Moin Rohwedder,

mir gefällt Deine letzte Version deutlich besser! ;)
tm6464
Posts: 48
Joined: 17 Jul 2017, 22:56

Re: random - no repeat

23 Mar 2019, 05:18

thx Rohwedder für deine zeit und mühe
Ich habe das jetzt schon anders (vll auch besser) gelöst damit es auch mit mehreren dateien funktioniert
Mein script poste ich mal vll hat jemand irgendwann das gleiche problem und sucht eine schnelle lösung

Code: Select all



Gui, Add, Button, x6 y7 w90 h20 gbutton1, button1
Gui, Show, w177 h204, New GUI Window
Return

button1:
gosub, funktionchat1
sleep, 100
loop,10
{
gosub, randomsend1
sleep, 1000
}
tooltip, 1-done
gosub, funktionchat2
sleep, 100
loop,10
{
gosub, randomsend2
sleep, 1000
}
tooltip, 2-done
return

;---------------------------------------
funktionchat1:
Loop, read, chat1.txt
{
  question%A_index% := A_LoopReadLine
  maxquestion := A_index
}
ObjectCreate1: 
Obj:=[]
Loop, %maxquestion%
Obj.Push(A_Index) 
return

randomsend1:
Random, item, 1, % Obj.MaxIndex() 
number:=Obj[item] 
Obj.Delete(number) 
If Obj.MaxIndex()=0
   GoSub, ObjectCreate1
tooltip % question%number%
return
;---------------------------------------
funktionchat2:
Loop, read, chat2.txt
{
  question%A_index% := A_LoopReadLine
  maxquestion := A_index
}
ObjectCreate2: 
Obj:=[]
Loop, %maxquestion%
Obj.Push(A_Index) 
return

randomsend2:
Random, item, 1, % Obj.MaxIndex() 
number:=Obj[item] 
Obj.Delete(number) 
If Obj.MaxIndex()=0
   GoSub, ObjectCreate2
tooltip % question%number%
return
;---------------------------------------

just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat

23 Mar 2019, 06:08

Hallo tn6464,

die Idee ist an sich nicht schlecht. Ich glaube aber nicht, dass das so funktioniert.
  • Du verwendest für beide Chatroutinen dieselbe Variable Obj als Array für die Zeilennummern.
  • Obj.Delete(number) verändert Obj.MaxIndex() nur dann, wenn number zufällig den maximalen Index des Arrays enthält. Was Du machen willst, ist wohl eher Obj.RemoveAt(number).
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: random - no repeat

23 Mar 2019, 06:10

Meine Idee:
Du hast eine Urne in der du alle Sätze die möglich sind hinzufügst.
Wenn du einen Satz brauchst ziehst du einen zufälligen aus der Urne.
Als Urne verwenden wir ein Array:

Code: Select all

urne := []
Um dem array Bälle aus einer datei hinzuzufügen verwenden wir:

Code: Select all

urne.push(StrSplit(FileOpen(textDatei,"r`n").Read(),"`n")*)
Hier passiert ne Menge in einer Zeile:
FileOpen(textDatei,"r`n") Öffnet eine Datei fürs lesen und gibt ein file objekt zurück. Der Name der Datei wird durch die variable textDatei bestimmt.
….Read() liest den Text eines FileObjektes und gibt ihn ganz zurück.
Per StrSplit(…,"`n") erzeugen wir aus dem Text einen Array der bei jeder Zeile getrennt ist.
Und als letztes fügen wir dieses Array per Urne.push(…*) diesen Array dem Urnen Array hinzu.

Als letztes brauch man nur eine Möglichkeit einen zufälligen Satz zu ziehen und diesen aus der Urne zu entfernen.

Code: Select all

Random, gezogenerSatz, 1, % urne.length()
satzText := urne.removeAt(gezogenerSatz)
Wobei dann satzText den text des gezogenen Satzes enthält.
Recommends AHK Studio
tm6464
Posts: 48
Joined: 17 Jul 2017, 22:56

Re: random - no repeat

23 Mar 2019, 08:06

@just me
also bisher funktionierts so
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat

24 Mar 2019, 03:17

@tm6464: Dann funktioniert es aber anders, als Du ursprünglich gefordert hast. Ich kann nue von dem Code ausgehen, den Du eingestellt hast. Wenn ich den hier mit folgender Datei für Chat1 und Chat2 laufen lasse

Code: Select all

Zeile 1
Zeile 2
Zeile 3
Zeile 4
Zeile 5
Zeile 6
Zeile 7
Zeile 8
Zeile 9
Zeile 10
produziert er beispielhaft folgende Ausgaben:

Code: Select all

---------------------------
Test.ahk
---------------------------
Chat1..........:
Zeile 8
Zeile 5
Zeile 4
Zeile 2
Zeile 10

Zeile 7
Zeile 1


..........1 done

Chat2..........:
Zeile 3
Zeile 5
Zeile 7
Zeile 8

Zeile 10

Zeile 4

Zeile 2
..........2 done
---------------------------
OK   
---------------------------
Fällt Dir etwas auf?
tm6464
Posts: 48
Joined: 17 Jul 2017, 22:56

Re: random - no repeat

24 Mar 2019, 05:53

@just me da hast du sicher recht, das script ist nicht perfekt für meine anwendung gehts hald so auch
wenn du weisst wie kannst du es gerne so anpassen das es perfekt ist , ich bin dazu nicht in der lage und froh das überhaupt jetzt so geht
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: random - no repeat  Topic is solved

24 Mar 2019, 08:42

Hallo,

das folgende Codeschnipsel enthält zwei Funktionen, die für Deine Aufgabe taugen sollten:
  • FileToArray(FileName)
    liest eine Datei und gibt die Zeilen als Array zurück.
  • RandomArray(SimpleArray)
    baut aus diesem Array ein zufällig sortiertes Array mit den Zeilennummern auf und gibt es zurück.

Code: Select all

FileToArray(FileName) {
   If !(FileHandle := FileOpen(FileName, "r"))
      Throw "Die Datei " . FileName . " konnte nicht geöffnet werden!"
   FileContent := FileHandle.Read()
   FileHandle.Close()
   Return StrSplit(RTrim(FileContent, "`n`r"), "`n", "`r")
}
RandomArray(SimpleArray) {
   SortVar := ""
   For Index In SimpleArray
      SortVar .= Index . "`n"
   Sort, SortVar, Random
   Return StrSplit(RTrim(SortVar, "`n"), "`n")
}
Du musst nun pro Chatdatei am Anfang des Skripts einmal die Funktion FileToArray() aufrufen und ein zunächst leeres Zeilennummernarray anlegen, z.B.

Code: Select all

Chat1FileArray := FileToArray("Chat1.txt")
Chat1RandArray := []
Die Routine, die die zufälligen Zeilen ausgibt, könnte dann so aussehen:

Code: Select all

Chat1Label:
   If (Chat1RandArray.Length() = 0)
      Chat1RandArray := RandomArray(Chat1FileArray)
   Rand := Chat1RandArray.Pop()
   MsgBox, 0, #%Rand%, % Chat1FileArray[Rand]
Return
tm6464
Posts: 48
Joined: 17 Jul 2017, 22:56

Re: random - no repeat

25 Mar 2019, 05:37

wow respekt, funktioniert wirklich perfekt
ich verstehe nicht jede deiner zeilen aber habe das mal so eingefügt, hoffe es passt so

Code: Select all

Mbutton::
Chat1FileArray := FileToArray("Chat1.txt")
Chat1RandArray := []
loop, 3
{
gosub, Chat1Label
sleep, 1000
}
Chat1FileArray := FileToArray("Chat2.txt")
Chat1RandArray := []
loop, 5
{
gosub, Chat1Label
sleep, 1000
}
tooltip, end
return

Chat1Label:
   If (Chat1RandArray.Length() = 0)
      Chat1RandArray := RandomArray(Chat1FileArray)
   Rand := Chat1RandArray.Pop()
   tooltip, % Chat1FileArray[Rand]
Return


FileToArray(FileName) {
   If !(FileHandle := FileOpen(FileName, "r"))
      Throw "Die Datei " . FileName . " konnte nicht geöffnet werden!"
   FileContent := FileHandle.Read()
   FileHandle.Close()
   Return StrSplit(RTrim(FileContent, "`n`r"), "`n", "`r")
}
RandomArray(SimpleArray) {
   SortVar := ""
   For Index In SimpleArray
      SortVar .= Index . "`n"
   Sort, SortVar, Random
   Return StrSplit(RTrim(SortVar, "`n"), "`n")
}
User avatar
Scr1pter
Posts: 1272
Joined: 06 Aug 2017, 08:21
Location: Germany

Re: random - no repeat

25 Mar 2019, 15:48

Eine Frage:
Warum arbeitest du nicht mit einer Funktion statt mit goSub?
In den Doks steht:
Obwohl Gosub für einfache, allgemeine Subroutinen nützlich ist, wäre es ratsam, für komplexere Anliegen Funktionen zu verwenden.
Ich selbst bin überhaupt kein Fan von goSub und goto.

Grüße
Please use [code][/code] when posting code!
Keyboard: Logitech G PRO - Mouse: Logitech G502 LS - OS: Windows 10 Pro 64 Bit - AHK version: 1.1.33.09

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 52 guests