Zufallswert (Programm stop)

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Ufaschu

Betreff: Zufallswert (Programm stop)

BeitragFr, Sep 07, 2012 12:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich versuche gerade mit Zwei Functionen eine Zeilenauslesung einer txt Datei.
Es soll immer nur eine Zeile ausgegeben werden (per zufall).

Variable: Die soll den zufallswert enthalten und sobalt man den menüpunkt wieder aufruft soll ein anderer wert dort drinnen stehen um eine Andere Zeile auszulesen.
Zitat:
Global zahlr


Function: Zufällige Zahl anhand der Zeilenmenge in der txt erstellen
Zitat:

Function perzufall()
filein = ReadFile("test.txt")
zaehler= 0
While Not Eof(filein)
ReadLine(filein)
zaehler= zaehler + 1
Wend
CloseFile filein
SeedRnd MilliSecs()

For i = 0 To zaehler
zahlr = Rnd(0,zaehler)
Next

Text 10,20, zahlr
End Function


Function: Hier wird die Zeile ausgelesen und zerteielt.
Zitat:

Function Textfeld()
zahl = zahlr
fragen=OpenFile("test.txt")
read_frage$=ReadLine (fragen)

While Not pos >= 1
zeilen$ = ReadLine(fragen)
Pos = Instr (zeilen$, zahl)
Wend
CloseFile (fragen)

Split(zeilen$, ";")
For i = 0 To SplitCount
Text 20,200, SplitString(0)
Text 20,210, SplitString(1)
Text 20,220, SplitString(2)
Text 20,230, SplitString(3)
Text 20,240, SplitString(4)
Next
End Function


Aufgeruffen wird das ganze dann hier im Schleifenteil des Programms
Zitat:

Repeat
.....
Else If gamezustand = 1 Then
While gamezustand = 1
Cls
Hintergrund_Game()
Gamemenu()
;Sound_Fragen()
perzufall()
Textfeld()

Maus_Zeichnen()
Flip
Wend
.....
Else
End
End If

Flip
Until KeyHit(1)


Was habe ich versucht:
Ich habe beide Functionen schon in eine gepackt, dann lauft die Zahl (Zufallswert) unentwegt weiter und es wird dann nur die erste zeile ausgegeben aber das Programm hält nicht an.

Mache ich es so wie hier hält das Programm an aber es werden nach Beenden und dann Neustart die Zeilen per Zufall ausgegeben.

Zufall habe ich sowohl mit Rand und Rnd versucht, mit oder ohne For schleife.
Ich komme da einfach nicht mehr weiter.

SpionAtom

BeitragFr, Sep 07, 2012 12:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Ufaschu, mir sind gleich einige Dinge aufgefallen.

Deine Function perzufall ist ein perfektes Beispiel für eine Funktion mit Parameter und Rückgabewert.
Was du willst, ist eine Datei hereingeben, und herausbekommen willst du einen Zufallswert, der innerhalb der Zeilen-Anzahl liegt.
Code: [AUSKLAPPEN]

Function perzufall(datei$)

  .
  .
  .

  return Rand(0, zaehler)
End Function



Diese Schleife versteh ich nicht. Der Code liefert auch ohne die Schleife genau dasselbe, nur schneller.
Code: [AUSKLAPPEN]

For i = 0 To zaehler
zahlr = Rand(0,zaehler)
Next

Text 10,20, zahlr


Überhaupt solltest du für die zufällige Zeilenermittlung Rand verwenden, da du ja eine ganze Zahl suchst.



Und hier haste nen Beispielcode:
Code: [AUSKLAPPEN]
;http://www.blitzforum.de/forum/viewtopic.php?t=38964

Graphics 400, 300, 0, 2
SetBuffer FrontBuffer()


   ;Hauptschleife
   Repeat
      Print zufaelligeZeileAus("text.txt")
      WaitKey()
   Until KeyDown(1)
   End

Function zufaelligeZeileAus$(datei$)

   laenge = dateiLaenge(datei$)
   zufallszeile = Rand(1, laenge)
   file = ReadFile(datei$)
   For i = 1 To zufallszeile
      zeile$ = ReadLine(file)
   Next
   CloseFile file

   Return zeile$

End Function


Function dateiLaenge(datei$)

   file = ReadFile(datei$)
   laenge = 0
   While Not Eof(file)
      ReadLine(file)
      laenge = laenge + 1
   Wend
   CloseFile file

   Return laenge

End Function


An diesem Code ist aber noch nicht alles gut. Die beiden Functionen machen ähnliche Dinge, zudem ist es nicht gut, ständig eine Datei neu zu öffnen, obwohl man weiß, dass immer dasselbe drinsteht. Besser ist es, wenn man zu Beginn einmal die Datei einliest und in ein Array abspeichert. Aber dazu mehr, wenn du das erstmal verstanden hast Very Happy
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080
 

Ufaschu

Betreff: Danke

BeitragFr, Sep 07, 2012 12:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank, ich werde das mal verinnerlichen und gleich ausprobieren.

Ich denke mal damit kann ich mein Problem lösen, zumindest versuche ich es sofort.

Mit dem Datei einlesen hast Du recht, das war blödsinn die doppelt einzulesen.
ich hab das nur gemacht weil ich beide Funktionen einzeln getestet hab.
 

PhillipK

BeitragFr, Sep 07, 2012 12:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
For i = 0 To zaehler
zahlr = Rand(0,zaehler)
Next

Text 10,20, zahlr


Bei diesem part habe ich anfangs auch etwas gestutzt. ich denke, die intention dahinter ist, die zahl weiter "zu verzufälligen" - evtl lief sie anfangs so schnell, das durch Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
immer der selbe Seed gesetzt wurde.

Das ganze kannst du evlt durch eine rechnung verändern.
Zb holst du dir, bevor du SeedRnd setzt, erst noch eine letzt zufallszahl (von 1 bis 10000 ?) und verrechnest die mit deinem Zähler und den Millisecs(). (Bsp: Ms / Zähler * RandomZahl).
Setzt du diesen wert nun als SeedRnd ein, kommt - je nach programmaufbau (dh wenn du öfters Rnd / Rand verwendest) andere zahlen raus.

Solltest du nur dort Rand/Rnd verwenden, so erübrigt sich SeedRnd komplett und es reicht, wenn du dieses einmalig zu programmstart ausführst.

Zweiter punkt:

Du liest jedesmal die Datei aus. An sich kann man da ja tun, mir persöhnlich ist meine festplatte wichtiger.
Ich denke, du wirst in deinem Programm genau wissen, wann du etwas aus der Datei herausnimmst bzw reinschreibst. Für diesen fall solltest du dort nur nach einem update deiner Datei die zeilen zählen. Speicher diesen Wert global ab und du hast gleich 2 Fliegen mit einer klappe: 1) Zugriffszeiten auf die Festplatte fallen weniger ins gewicht -> speedboost. 2) Festplatten lebzeit *geringfügig* länger. Oder anders: Es ist schöner.

Dritter punkt:

SpionAtom hats bereits erwähnt: Lass deine funktion doch einfach einen zufallswert zurückgeben Smile

Vierter punkt:
Zitat:
aber das Programm hält nicht an.

Das verstehe ich nicht. Ich sehe keinerlei grund, warum dein programm anhalten sollte. Sprich: es wird nicht abgefragt.
Kannst du diese aussage genauer erklären?

Ich rate nun mal ein wenig weiter, was nicht stimmen könnte:

Code: [AUSKLAPPEN]
While Not pos >= 1
zeilen$ = ReadLine(fragen)
Pos = Instr (zeilen$, zahl)
Wend


Ich verstehe nicht, wieso du diese funktion anders hast, als deine Zählfunktion.

Mein ansatz wäre da etwa so : (zum verständniss: ich blick grade einfach nicht durch *g* Was bezweckt jede dieser variablen? Die namen sind nicht ausschlagkräftig genug für mein hirn.)

BlitzBasic: [AUSKLAPPEN]

zaehler= zahlr
pos = 0
lastLine$ = ""
While Not Eof(fragen) And zaehler > pos
lastLine$ = ReadLine(fragen)
pos = pos+1

Wend
If pos < zaehler Then
;problemfall: die datei war kleiner, als zahlr angibt. Hier evtl nochmal von vorn, neue zufallszahl etc, evtl zeilenanzahl neu einlesen.
EndIf

;hier ist lastLine deine wunsch-zeile in der txt datei. zumindest in meiner theorie :D

DAK

BeitragFr, Sep 07, 2012 17:23
Antworten mit Zitat
Benutzer-Profile anzeigen
PhillipK hat Folgendes geschrieben:
Code: [AUSKLAPPEN]
For i = 0 To zaehler
zahlr = Rand(0,zaehler)
Next

Text 10,20, zahlr


Bei diesem part habe ich anfangs auch etwas gestutzt. ich denke, die intention dahinter ist, die zahl weiter "zu verzufälligen" - evtl lief sie anfangs so schnell, das durch Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
immer der selbe Seed gesetzt wurde.

Das ganze kannst du evlt durch eine rechnung verändern.
Zb holst du dir, bevor du SeedRnd setzt, erst noch eine letzt zufallszahl (von 1 bis 10000 ?) und verrechnest die mit deinem Zähler und den Millisecs(). (Bsp: Ms / Zähler * RandomZahl).
Setzt du diesen wert nun als SeedRnd ein, kommt - je nach programmaufbau (dh wenn du öfters Rnd / Rand verwendest) andere zahlen raus.

Solltest du nur dort Rand/Rnd verwenden, so erübrigt sich SeedRnd komplett und es reicht, wenn du dieses einmalig zu programmstart ausführst.


Zufälliger als mit einem SeedRnd Millisecs() wird's nicht. Millisecs() gibt die Zeit zurück, die der Computer aufgedreht ist, nicht wie lange das Programm schon läuft. Da jede weitere Zahl, die Rand zurück gibt, darauf basiert, was davor ist, ist es um keinen Deut zufälliger geworden, was daraus kommt.
Wenn du vor dem Code z.B. SeedRand(5) eingibst, und die gleiche Zahl in zaehler hast, dann kommt genau das Gleiche raus, nur dass du ungleich mehr Rechenzeit verschwendest.
Gewinner der 6. und der 68. BlitzCodeCompo
 

BBPro2

BeitragFr, Sep 07, 2012 23:23
Antworten mit Zitat
Benutzer-Profile anzeigen
abgesehen davon dass millisecs () die zeit seit start des pcs und nicht seit start des programms ausgibt (im anderne fall wäre es durchaus sinnvoll die millisecs() weiter zu verrechnen)
bringt es wie bereits von meinem vorredner erklärt rein gar nichts es mit "zufallszahlen" zu verrechnen
die man eben auf die gleiche art erhalten hat.

beispiel:

a = rand (0, 10)
seedrnd millisecs ()
b = rand (0, 10) * a
seedrnd b

- a ist hier keine zufallszahl sondern verdammt deterministisch, da kein seed gesetzt wurde.
- seedrnd millisecs () ist ebenfalls deterministisch wenn millisecs () immer 0 ist weil das programm
so schnell ist (ist hier wie gesagt ja eh anders)
- b ist demnach ebenfalls deterministisch, da immer der gleiche seed gesetzt wird
somit ist seedrnd b ebenfalls deterministisch.


wenn man einen seed mit anderen zahlen verrechnen will darf man keine vom zufallsgenerator erzeugten zahlen benutzen sondern muss unabhängige werte benutzen.

temperatur der cpu, maus-x-koordinate des ersten user-clicks, die dauer des ersten keystrokes - sowas - aber keine "zufallswerte"

DAK

BeitragSa, Sep 08, 2012 11:14
Antworten mit Zitat
Benutzer-Profile anzeigen
laut dem hier wird MilliSecs zumindest in B3D (angeblich ist das in Monkey anderst) von Start des Windows gerechnet, und das ist wohl die zufälligste und am einfachsten erreichbare Zahl, die man wohl bekommen wird. Vorallem da ja auch ein Seed der sich nur um eins von einem Anderen unterscheidet, eine ganz andere Folge Zufallszahlen bietet.
Gewinner der 6. und der 68. BlitzCodeCompo
 

BBPro2

BeitragSa, Sep 08, 2012 18:07
Antworten mit Zitat
Benutzer-Profile anzeigen
dem hab ich auch gar nicht widersprochen Wink

es ist genau so:

BB, BB+, BB3d, BMax: Millisecs () -> Zeit seit Systemstart
Monkey -> Zeit seit Programmstart
(um einen seed in monkey zu setzen sollte man daher RealMilliSecs() aus dem Diddy-Framework verwenden)


meine erläuterungen sollten nur einem besseren verständnis dienen und waren unter der vorbedingung, dass millisecs () die zeit seit programmstart zurückgibt, was - wie ich bereits im letzten post klargestellt habe - nicht der fall ist.
also nur theoretisches geplänkel für ein vertieftes verständnis Wink
 

PhillipK

BeitragSo, Sep 09, 2012 5:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich muss meine ausdrucksweise erklären Very Happy

Zitat:
Bei diesem part habe ich anfangs auch etwas gestutzt. ich denke, die intention dahinter ist, die zahl weiter "zu verzufälligen" - evtl lief sie anfangs so schnell, das durch Code:
SeedRnd MilliSecs()
immer der selbe Seed gesetzt wurde.


Mit "immer der selbe" seed hatte ich im hinterkopf, das die funktion evtl mehrmals hintereinander ausgeführt wird, undzwar in einem abstand von < 1ms -> Ergo, Millisecs() liefert mehrmals den gleichen wert.
Obgleich ich mir das bei FileOperationen nicht vorstellen kann, das sie "so wenig zeit" beanspruchen, halte ich es dennoch für sinnvoll, den SeedRnd woanders auszuführen, und nicht innerhalb einer funktion.
Sprich: Zum Programmstart Wink

Das weiterverrechnen der Zufallszahl bezog sich darauf, das eben dies nötig ist, falls wirklich explizit SeedRnd an dieser Stelle von nöten ist und mit meiner rechnung auch nur, wenn sich die zeilenzahl ändert Smile Ansonsten, wenn SeedRnd nötig ist und die funktion mehrmals in einer millisekunde ausgeführt werden muss, ist natürlich etwas anderes brauchbarer. Zb ein simpler counter, wie oft die funktion ausgeführt wurde, welche ebenfalls "verrechnet" wird =)

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group