Zufällige Zahlen Liste

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

FosJonas

Betreff: Zufällige Zahlen Liste

BeitragMi, Mai 20, 2009 15:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,
habe mir vor einer woche Blitzbasic gedownloadet und versuche gerade mein erstes spiel in blitzbasic zu programmieren.
dabei treffe ich aber auf dieses problem:
Ich will eine zufällige Liste erstellen die alle zahlen von 1-8 enthält, dabei soll jede zahl nur einmal vorkommen. ich habe das so veruscht:
Code: [AUSKLAPPEN]

For x= 1 To 8
Nummer(10+x)=x
Next
For x= 1 To 8
Nummer(4)=Nummer(10+Rand(1,8-x))
Game_List(x)=Nummer(4)
For y=Nummer(4) To 7
Nummer(10+y)=Nummer(11+y)
Next
Next
EndIf

das ergibt zwar eine liste aber es kommen immer manche zahlen doppelt und dreifach drin vor. warum?

The_Nici

BeitragMi, Mai 20, 2009 15:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Versteh deinen Ansatz überhaupt nicht, aber so hätte ich das gemacht:
Code: [AUSKLAPPEN]

SeedRnd MilliSecs()
Dim randomlist(7)

For i = 0 To 7
   Repeat
      zahl = Rand(1,8)
      For c = 0 To 7
         If randomlist(c) = zahl Then Exit
         If randomlist(c) = 0 Then
            randomlist(c) = zahl
            Exit
         EndIf
      Next
   Until c = 7
Next

For i = 0 To 7
   Print randomlist(i)
Next
WaitKey()

Ich prüfe das Dim-Feld, wenn es darin eine gleiche Zahl hat geht es aus der inneren For-Schleife, was zur Konsequenz hat, dass c nicht bis auf 7 gezählt wird, und so die Bedingung der Repeat-Schleife nicht erfüllt wird, also sich die Schleife wiederholt, bis die Zahl einzigartig ist.
Das ganze mache ich 7 mal und gebe danach die Liste aus.

MfG

Starwar

BeitragMi, Mai 20, 2009 15:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe meine eigene Methode.
Ich fülle eine Array mit den Zahklen von 1 bis 8.
Dann tausche ich ein paar viele mal zwei zufällig ausgwählte Einträge.
Vorteil: Nehmen wir an, wir haben eine Millionen Zahlen und haben schon 999.998 ermittelt. Jetzt bleiben nur noch zwei. Die Chance, dass genau einer dieser 2 per zufall ausgewählt wird, ist ziemich gering....

Code: [AUSKLAPPEN]
Dim zahlen(7)
For i=0 To 7
   zahlen(i) = i+1
   Print zahlen(i)
Next
For i=0 To 8*8
   zufall1%=Rand(0,7)
   zufall2%=Rand(0,7)
   tmp% = zahlen(zufall1%)
   zahlen(zufall1%) = zahlen(zufall2%)
   zahlen(zufall2%) = tmp%
Next
Print "------------"
For i=0 To 7
   Print zahlen(i)
Next
WaitKey()


MFG
  • Zuletzt bearbeitet von Starwar am Mi, Mai 20, 2009 15:39, insgesamt einmal bearbeitet

FosJonas

BeitragMi, Mai 20, 2009 15:37
Antworten mit Zitat
Benutzer-Profile anzeigen
wow danke für die schnelle hilfe, jetzt funktioniert es. Very Happy

Hmm mein ansatz war wohl wirklich völlig falsch, aber nun weis ich ja wies geht.

The_Nici

BeitragMi, Mai 20, 2009 15:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Ui, Starwars Methode ist um 0.04 Millisekunden schneller. Sad

FosJonas

BeitragMi, Mai 20, 2009 15:44
Antworten mit Zitat
Benutzer-Profile anzeigen
hmmm starwars seine methode raff ich nicht so ganz.
Naja 0,04 millisekunden sind mir eig. egal^^

Starwar

BeitragMi, Mai 20, 2009 16:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,
Also erstmal das Problem:
Wenn wir einfach so lange probieren, bis wir eine Zahl durch Zufall finden, die noch nicht in der Liste ist, können wir uns totsuchen. Das PRogramm "läuft sich Tot".
Nehmen wir an, wir haben eine Millionen Zahlen und haben schon 999.998 ermittelt. Jetzt bleiben nur noch zwei. Die Chance, dass genau einer dieser 2 per zufall ausgewählt wird, ist ziemlich gering....

Meine Lösung:
Stell dir ein Kartenspiel vor. Alle Karten sind von 1-36 durchnummeriert und in Reihenfolge.
Code: [AUSKLAPPEN]
Dim zahlen(7)
For i=0 To 7
   zahlen(i) = i+1
Next


Jetzt nimmst du dir irgendeine Karte. Und eine zufällige Zeite. (das kann auch die selbe sein, ist egal)
Code: [AUSKLAPPEN]
   zufall1%=Rand(0,7)
   zufall2%=Rand(0,7)


Dann tauschen wir die Karten
Code: [AUSKLAPPEN]
   tmp% = zahlen(zufall1%)
   zahlen(zufall1%) = zahlen(zufall2%)
   zahlen(zufall2%) = tmp%


Und das ganze machen wir ein paar mal (Ich nehm gerne das Quardrat der Anzahl der Werte (hier 8*8)).

Ich gehe nochmal genau auf diesen Code ein:
Code: [AUSKLAPPEN]
   tmp% = zahlen(zufall1%)
   zahlen(zufall1%) = zahlen(zufall2%)
   zahlen(zufall2%) = tmp%

Zuerst merken wir uns die 1. Zahl in einer Variable. Jetzt überschreiben wir nämlich die Variable in der die 1. Zahl liegt mit der 2.. Dann wissen wir die 1. natürlich nicht mehr, da wir sie überschrieben haben. Aber dafür ist die TMP-Variable. Die weiß die 1. Zahl noch. Also hat die Variable, in der die 2. Zahl ist jetzt den Wert der TMP-Variable. So haben wir die 1. und 2. Zahl getauscht.

Ich hoffe es ist nachvollziehbar...Wink

MFG
Und herzlich Willkommen im Portal.

das wurgel

BeitragMi, Mai 20, 2009 16:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

Hab hier noch ne schnellere Methode, die auch für beliebig große Anzahlen von Zahlen anwendbar sein müsste:
Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
Dim randomlist(7)

For i = 1 To 8
   zahl = Rand(1, 8-i+1)
   k=0
   For j = 0 To 7
      If randomlist(j)=0 Then
         k=k+1
         If k=zahl Then randomlist(j)=i
      EndIf
   Next
Next
   
For i = 0 To 7
   Print randomlist(i)
Next
WaitKey()

In der Schleife werden alle Zahlen von 1 - 8 durchgegangen. Dann wird per Zufall ausgewählt, die wievielte freie Stelle im Feld die Zahl gespeichert werden soll.

Also z.B. wird in der ersten Schleifenrunde eine Zahl von 1 - 8 ausgewählt. Nehmen wir an diese Zahl wäre 5. In der nächsten Runde wird eine Zahl von 1 - 7 gewählt weil die Stelle 5 im Feld schon besetzt und daher noch 7 Stellen übrigbleiben. Die 5 Stelle wird dann nicht mehr mitgezählt und eine 7 würde bewirken dass die 8. Stelle mit der Zahl 2 gefüllt wird usw.

mfg
1 ist ungefähr 3

Starwar

BeitragMi, Mai 20, 2009 16:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr schöne Methode, wenn sie mir auch nicht sofort eingeleuchtet ist. Totlaufen kann sie sich jedenfalls nicht und zufälliger gehts auch nicht Wink
Aber wenn du sehr auf Geschwindigkeit wert legst, dann hab ich noch eine kleine Ergänzung: Code: [AUSKLAPPEN]
If k=zahl Then randomlist(j)=i : Exit
Wink
MFG
 

Kruemelator

BeitragMi, Mai 20, 2009 18:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe hier auch nochmal eine ganz andere Methode.
Sie ist auch ein ganz wenig schneller als die von das wurgel.
Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
Dim zahlen(7)
zahlenreihe$ = "12345678"

For x=0 To 7
   stelle = Rand(0,7-x)+1
   zahlen(x) = Mid(zahlenreihe$ ,stelle  ,1)
   zahlenreihe$ = Replace(zahlenreihe$, zahlen(x), "")
Next

For a=0 To 7
Print zahlen(a)
Next


Es wird ein String erstellt mit den Zahlen die enthalten sind. Dann wir eine zufällige Stelle gewählt und die Zahl die dort steht in dem Dim Feld gespeichert und diese Stelle aus dem String gelöscht.

Gruß Kruemelator

TimBo

BeitragMi, Mai 20, 2009 18:47
Antworten mit Zitat
Benutzer-Profile anzeigen
boah wie geil, hier sieht man mal wie man sauber und unsauber programmieren kann. Gerade The_nici hat ein echt sehr cooles Beispiel gebracht. Wenn man 10000 Zahlen haben wird dieser Code schon echt viel lahmer als die anderen.
@The_Nici: ich möchte dich nicht Blosstellen oder so, aber daraus kann man doch lernen oder? Dein Ansatz ist am einfachsten zu verstehen und eigentlich vom normalen verstand doch der logischste , aber allerdings nicht der beste.

Das mit dem String ist das vom gedankengang strangste aber echt einleuchtend. Man löscht einfach das verwendete und schon hat sichs.
Echt coole überlegung

Viele Grüße
TimBo
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31
hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht.

Starwar

BeitragMi, Mai 20, 2009 19:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich denke bei 8 Zahlen müssen wir kein Geschwindikeitsrekord aufstellen Wink
Aber bei 1000 schon... Die String-Methode wird bei unterschiedlich-ziffrigen Zahlen schon komplizierter. Aber sie zeigt wie viele intressante Lösungen es für dieses Problem gibt. Sehr inspirierend Wink
MFG
 

Kruemelator

BeitragMi, Mai 20, 2009 20:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Herausforderung angenommen Very Happy
Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
Dim zahlen(999)
zahlenreihe$ = ""


time1 = MilliSecs()
For stelle100=0 To 9
For stelle10=0 To 9
For stelle1=0 To 9
zahlenreihe$ = zahlenreihe$ + "-" + stelle100 + "" + stelle10 + "" + stelle1
Next
Next
Next

time2 = MilliSecs()
For x=0 To 999
   stelle = Rand(0,999-x)
   wert$ = Mid(zahlenreihe$ ,stelle*4+1  ,4)
   zahlen(x) = Right(wert$,3)
   zahlenreihe$ = Replace(zahlenreihe$, wert$, "")
Next
time3 = MilliSecs()
Print time3 - time1
Print time3 - time2

;datei = WriteFile("c:\zahlenliste.txt")
;For a=0 To 999
;WriteLine datei,zahlen(a)
;Next
;CloseFile datei



Edit:
Man kann mit Strings auch andere Probleme lösen:
Z.B.: Socken aus Schrank ziehen Laughing wo mehrere die gleiche Farbe haben, also mehrmals die selbe vorkommt.
Code: [AUSKLAPPEN]
SeedRnd MilliSecs()
Dim zahlen$(8)
zahlenreihe$ = "-r-r-r-g-g-b-b-b-b"

;Print zahlenreihe$
For x=0 To 8
   stelle = Rand(0,8-x)
   wert$ = Mid(zahlenreihe$ ,stelle*2+1  ,2)
   zahlen$(x) = Right(wert$,1)
   vorher = Len(zahlenreihe$)
   zahlenreihe$ = Replace(zahlenreihe$, wert$, "")
   nachher = Len(zahlenreihe$)
   
   wiederholungen = (vorher - nachher)/2 -1
   While wiederholungen <> 0
   zahlenreihe$ = zahlenreihe$ + "" + wert$
   wiederholungen = wiederholungen - 1
   Wend
   ;Print zahlenreihe$
Next

For a=0 To 8
Print zahlen(a)
Next

Starwar

BeitragMi, Mai 20, 2009 21:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Wohl nen Clown gefrühstückt, was? Wink
Gute Ideen, ich werds mir auf jedenfall merken. In PHP mach ichs bereits, da gibts die schöne Funktion "explode". Ich glaube ich werd die jetzt mal schnell nachcoden...

Hier ist sie nun. Aber es geht gewiss noch eleganter... Razz
Code: [AUSKLAPPEN]
Dim exploded$(0)

AppTitle "Exploding String"
in$ = "Dieser String ist explodiert oder so was in der Art..."
anz = explode(in$," ")
For i=0 To anz-1
   Print exploded$(i)
Next
WaitKEy()
End

Function explode(in$,tz$)
   pos=Instr(in$,tz$)
   If pos=0 Then
      Dim exploded$(0)
      exploded$(0)=in$
      Return 1
   EndIf
   Repeat
      pos=Instr(in$,tz$,pos+1)
      anz=anz+1
      If pos = 0 Then Exit
   Forever
   Dim exploded$(anz)
   pos=0
   altpos=0
   Repeat
      altpos=pos
      pos=Instr(in$,tz$,pos+1)
      If pos = 0 Then pos=-1
      exploded$(i)=Mid(in$,altpos+1,pos-1-altpos)
      i=i+1
      If pos=-1 Then Exit
   Forever
   Return anz+1
End Function

MFG

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group