BPS #10: Zufällige Anordnung - Auswertung

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

Xeres

Moderator

Betreff: BPS #10: Zufällige Anordnung - Auswertung

BeitragSo, Jul 24, 2011 14:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Wer hat eine Lösung gefunden, wem ist eine gute Idee gekommen?

Das war die Aufgabe

Postet hier eure Ergebnisse, Codes, Gedanken. Lernt von den anderen, seht euch deren Quelltext an und versucht euren eigenen zu verbessern.

Diskussion
Postet zu euren Codes stets eine kurze Erklärung mit euren Gedanken in denen ihr simpel gesagt die Frage "Wieso habe ich XY auf diese Art gelöst?" beantwortet. Beiträge, die nur den Code enthalten werden wir aus dem Thread entfernen.

Nächste Aufgabe
In zwei Wochen, wird die Musterlösung nach editiert und die nächste Aufgabe eingestellt.

Viel Spaß & viel Erfolg!

Musterlösung:

BlitzBasic: [AUSKLAPPEN]
;* Zufall ohne Doupletten

;* Fenster zum Anzeigen:
Graphics(256,256,32,2)
;* Der Zufallssamen wird mit der Laufzeit des Computers initialisiert
;* damit werden bei jedem Programmstart andere Zahlen generiert.
SeedRnd(MilliSecs())

;* 3x3 Feld (mit Zahlen 1-9 zu befüllen)
Dim Feld(2,2)

Local x, y, Nummern_Liste$=""
;* Alle Felder werden von oben nach unten...
For y=0 To 2
;* ...und von rechts nach links durchgegangen.
For x=0 To 2
;* Jetzt wird der folgende Vorgang wiederholt:
Repeat
;* Ein zufallszahl wird generiert
Feld(x,y)=Rand(1,9)
;* Wenn die Zufallszahl nicht im String enthalten ist,
;* wird die Schleife verlassen
Until Instr(Nummern_Liste,Feld(x,y))=0
;* Die Zufallszahl wird dem String hinzugefügt.
Nummern_Liste=Nummern_Liste+Feld(x,y)
Next
Next
;* Alle Felder wurden abgearbeitet

;* Anzeige der Felder:
For y=0 To 2
For x=0 To 2
Text(64+x*64, 64+y*64, Feld(x,y), True, True)
Next
Next

;* Diese Methode kann man offensichtlich nicht für beliebige Werte verwenden!
;* Würde man Zahlen von z.B. 1-11 generieren, würde "1" im String "11" enthalten sein.
;* Natürlich lassen sich Zahlen durch Symbole für Beginn und Ende Trennen;
;* "'1'" wird nicht im String "'11'" gefunden!

WaitKey()
End
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
  • Zuletzt bearbeitet von Xeres am So, Aug 07, 2011 17:48, insgesamt einmal bearbeitet

darth

BeitragSo, Jul 24, 2011 15:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

das war ja diesmal eine ziemlich einfache Aufgabe. Meiner Meinung nach war etwas viel vorgegeben (wieso gerade ein 3x3 Feld?), aber falls man sowas in der Art mal braucht, kann mans sich wahrscheinlich von der Lösung ableiten. Nun denn:

BlitzBasic: [AUSKLAPPEN]
SeedRnd( MilliSecs() )

Local x, y, xt, yt, alreadySet

Dim dat(3, 3)

For x = 0 To 2
For y = 0 To 2
While True
k = Rand(1, 9)

alreadySet = False

For xt = 0 To 2
For yt = 0 To 2
If dat(xt, yt) = k
alreadySet = True
EndIf
Next
Next

If Not alreadySet
dat(x, y) = k

Exit
EndIf
Wend
Next
Next

Local s$

For y = 0 To 2
s = ""

For x = 0 To 2
s = s + dat(x, y)
Next

Print s
Next

WaitKey()


SeedRnd soll den neuen Zahlengenerator initiieren, ich mache das auf Millisecs, damit das bei "jedem" Programmstart neue Zufallszahlen gibt (Zufälle ausgenommen). Dann das Feld definieren, da klar ist, was es für ein Feld sein muss, ist es mit einem 3x3 Dim gemacht. Könnte man auf verschiedene andere Arten auch machen, wird aber etwas komplizierter.

Die Doppelschleife x/y geht alle Felder durch, um sie mit Zahlen zu füllen. Weil man ja Goto nicht benutzen darf (hihi) steht dort eine While-Schleife, die (vorerst) einfach mal unendlich lange läuft. Dann wird eine neue Zufallszahl generiert (natürlich im Bereich [1,9]), und eine temporäre Variable auf False gesetzt. Dann wird mit der Doppelschleife xt/yt geprüft ob die Zahl schon gesetzt wurde, falls nein, wird sie eingefügt und die Schleife verlassen, falls ja - auf ein Neues!
Könnte man auch anders lösen, indem man zum Beispiel die Bedignung mit dem alreadySet direkt in den Schleifenkopf einfügt. Ich bevorzuge aber die Exit Methode, weil sie für mich persönlich klarer ist.

Die Ausgabe ist dann Formsache..

MfG,
Darth
Diese Signatur ist leer.

SpionAtom

BeitragSo, Jul 24, 2011 18:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Meine Lösung ist etwas anders. Ich benutze ein eindimensionales Array. Da die Lösung aber eine zweidimensionale Abbildung erwartet (3x3 Feld), muss ich die eindimensionalen Koordinaten in zweidimensionale umwandeln. Dazu gibt es folgende Umrechungen

Eindimensionale Koordinaten auf zweidimensioale übertragen
Code: [AUSKLAPPEN]

;i ist die eindimensionale Koordinate
;breite ist die Breite des Feldes - bei uns 3
x = i Mod breite
y = i / breite


Und zweidimensionale auf eindimensionale übertragen
Code: [AUSKLAPPEN]

i = x + y * breite



Damit keine Zahlen doppelt vorkommen, verwende ich die "Misch-Methode". Zunächst werden die Zahlen von 1 bis 9 nacheinander in das Array geschrieben. Jede Zahl ist jetzt einmal enthalten.
Im nächsten Schritt vertausche ich jeweils Felder, somit werden ihre Positionen vermischt, jedoch kommen nirgendwo Zahlen hinzu oder verschwinden -> Jede Zahl bleibt von Anfang an einmalig vertreten:

BlitzBasic: [AUSKLAPPEN]
	;Vorbereitung
breite = 3
hoehe = 3
start = 1
Dim feld(breite * hoehe - 1)
SeedRnd(MilliSecs())

;Feld füllem
For i = 0 To breite * hoehe - 1
feld(i) = start + i
Next

;Feld durchmischen
;Nacheinander wird jedes Feld im Array mit einem zufälligen anderen Feld getauscht
For i = 0 To breite * hoehe - 1
z = Rand(0, breite * hoehe - 1)
;Dreieckstausch
temp = feld(i)
feld(i) = feld(z)
feld(z) = temp
Next


;Ergebnis anzeigen
Graphics 400, 400, 0, 2
SetBuffer BackBuffer()

fgb = GraphicsWidth() / breite
fgh = GraphicsHeight() / hoehe

For i = 0 To breite * hoehe - 1
Text (i Mod breite + 0.5) * fgb, (i / breite + 0.5) * fgh, feld(i)
Next

Flip()
WaitKey
End

os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080

hazumu-kun

BeitragSo, Jul 24, 2011 20:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Den Mischen Ansatz hätte ich dann auch programmiert, hatte nur ganz übersehen, dass es eine neue BPS Aufgabe gibt Sad

Gibt es eigentlich eine Faustregel wie viele zufällige Tauschoperationen man auf ein Feld der Größe n anwenden muss bis es "gut" gemischt ist?
Warum kann es keine omnipotente Macht geben?
Weil diese omnipotente Macht in der Lage sein müsste, einen so schweren Stein zu schaffen, dass sie ihn nicht heben kann
-> nicht omnipotent

SpionAtom

BeitragSo, Jul 24, 2011 20:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich mische, indem ich der Reihe nach jedes Feld mit einem zufälligen anderen tausche, also breite * hoehe Tauschoperationen. Bin nicht so gut in Stochastik, aber mit dem Ergebnis bin ich gut zufrieden.
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080

Xeres

Moderator

BeitragSo, Jul 24, 2011 20:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Hübsche Beiträge. Bin auf weitere Versionen gespannt.

@hazumu-kun: Ich würde sagen, wenn jede Folge genauso wahrscheinlich vorliegt wie eine beliebig andere (123456789 eingeschlossen). Aus dem Bauch heraus würde ich n/2 als "gut genug" deklarieren: eine Tauschaktion wirkt sich auf 2 Positionen aus, womit bei n/2 theoretisch alle Positionen geändert worden sein könnten.
Für präzise Antworten musst du "gut" definieren, sonst kann man viel Mathe um nichts machen. Wink
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

aMul

Sieger des Minimalist Compo 01/13

BeitragSo, Jul 24, 2011 22:55
Antworten mit Zitat
Benutzer-Profile anzeigen
n/2 mal zu Tauschen ist zu wenig. Da einige Elemente mehr als einmal getauscht werden(mit sehr hoher Wahrscheinlichkeit) liegen im Schnitt zu viele Elemente in der Ausgangsposition.
Wenn man wie SpionAtom schon sagte n mal tauscht und zwar das Element in jeder Position mit einem zufälligen anderen kann man von einer gleichmäßigen Verteilung ausgehen(jedes Element wurde mindestens einmal vertauscht).
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

hazumu-kun

BeitragMo, Jul 25, 2011 0:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Smile
Warum kann es keine omnipotente Macht geben?
Weil diese omnipotente Macht in der Lage sein müsste, einen so schweren Stein zu schaffen, dass sie ihn nicht heben kann
-> nicht omnipotent

ZEVS

BeitragMo, Jul 25, 2011 12:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Meine Lösung ist die folgende:
BlitzBasic: [AUSKLAPPEN]
SeedRnd MilliSecs()

Const w=3, h=3

Dim numbers(w*h-1), used(w*h-1)
Global noOfNos

For noOfNos=1 To w*h
Local n = getUnused(Rand(1, w*h-noOfNos+1))
numbers(noOfNos-1) = n
Next

For y=1 To h
Print "+---+---+---+"
Print "| | | |"
For x=1 To w
Write "| "+numbers((y-1)*w+x-1)+" "
Next
Print "|"
Print "| | | |"
Next
Print "+---+---+---+"

Function getUnused(n)
For i=1 To n
If used(i-1) Then n = n+1
Next
used(n-1) = True
Return n
End Function

Local timer = CreateTimer(1)

For i=1 To 3
WaitTimer timer
Next

Code korrigiert

Ich verwende auch der Einfachkeit halber ein eindimensionales Array.
Es wird immer eine zufällige Zahl zwischen 1 und 9-n ermittelt, wobei n die Anzahl der bereits festgelegten Zahl ist. Entsprechend ist der Zahlenraum genau so groß, wie die Anzahl der unbefüllten Felder. D.h. wir haben eine 1:1 Zuordnung von möglichen Zahlen (zwischen 1 und 9-n) und fehlenden Zahlen. Diese Zuordnung wird von der Funktion getUnused vorgenommen. Der Rest des Codes beschäftigt sich mit Anzeige und Programmverzögerung (ich verwende B+, deshalb kein WaitKey). Die reicht zwar evtl. nicht zum lesen, aber um das Programm mit dem Debugger anzuhalten.

Die Lösung finde ich ehrlich gesagt eleganter als massives Tauschen
 

pinochino

BeitragMi, Jul 27, 2011 3:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo

Hier jetzt auch meine Lösungen, etwas verspätet aber nja.
Ich habe 2 Lösungen angefertigt.

Ein Mischverfahren, in welchem erst 9 Felder mit den Zahlen 1-9 gefüllt und dann untereinander getauscht (gemischt) werden.

BlitzBasic: [AUSKLAPPEN]
Const xmax%=800, ymax%=600, KEY_ESC%=1
Dim Feld%(3,3)
Graphics xmax,ymax,32,2
SetBuffer BackBuffer()
FPS=CreateTimer(60)
SeedRnd MilliSecs()
; Feld(x,y) mit 1 - 9 Füllen
i%=0
For x% = 1 To 3
For y% = 1 To 3
i = i+1
Feld(x,y)=i

Next
Next

;Felder Mischen
For j% = 1 To 1000
a%=Rand(1,3)
b%=Rand(1,3)
c%=Rand(1,3)
d%=Rand(1,3)


Tausch%=Feld(a,b)
Feld(a,b)=Feld(c,d)
Feld(c,d)=Tausch%
Next


Repeat
WaitTimer(FPS)
If KeyHit(KEY_ESC) Then Ende=1

;3x3 Feld Zeichnen
For x% = 1 To 3
For y% = 1 To 3
Text x*30, y*30,+Feld(x,y)
Next
Next

Flip 0
Cls
Until Ende=1
End


Und ein Zufallsverfahren, in welchem 9 Feldern je eine Zufallszahl (Zwischen 1-9) zugewiesen wird und darauf hin auf Doppelte Zahlen geprüft wird und jene ersetzt werden. Diese Zufallszahlen werden dann in ein Extra 3x3 Feld eingetragen und ausgegeben.

BlitzBasic: [AUSKLAPPEN]
Const xmax%= 800, ymax%= 600, KEY_ESC%=1
Dim Zahl%(9), Feld%(3,3)
Graphics xmax,ymax,32,2
SetBuffer BackBuffer()
FPS=CreateTimer(60)
SeedRnd MilliSecs()



;ZufallsZahl erstellen & auf Doppelte Zahlen Prüfen
For i = 1 To 9
Repeat
Local Doppel = 0
Zahl(i)=Rand(1,9)

For j = 1 To i-1
If Zahl(i) = Zahl(j) Then
Doppel = 1
EndIf
Next

Until Doppel = 0
Next

;3x3 Feld festlegen
i = 0
For x = 1 To 3
For y = 1 To 3
i = i+1
Feld(x,y) = Zahl(i)
Next
Next



Repeat
WaitTimer(FPS)
If KeyHit(KEY_ESC) Then End = 1
;Zeichnen
For x = 1 To 3
For y = 1 To 3
Text x*30,y*30,Feld(x,y)
Next
Next

Flip 0
Cls
Until End = 1
End


lg
pinO
 

dont_know_to_use

BeitragMi, Jul 27, 2011 10:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn dies ein Wettbewerb für die Anfänger ist, warum machen dann hier fast nur die klügsten Köpfe des Forums mit? Surprised
 

PhillipK

BeitragMi, Jul 27, 2011 11:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh, auch nicht kluge köpfe dürfen mitmachen? Very Happy

Ich denke, bevor da garnichts zu stande kommt, geben andere leute auch ihre beiträge ab.
Persönlich würde ich nicht behaupten, das ich noch ein absoluter anfänger bin, aber auch ich habe schon ein ums andere mal durch die bps geschaut und geguckt, wie die umsetzungen waren.
Das ist doch ein netter lernschritt.. erst die simplen umsetzungen durcharbeiten, dann die komplexen der "klugen köpfe" Very Happy
 

pinochino

BeitragMi, Jul 27, 2011 14:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe doch auch Teilgenommen obwohl Ich ein blutiger Anfänger bin Smile

Du kannst den BPS auch mit einem deiner Beiträge bereichern.

lg

Mr.Keks

BeitragMi, Jul 27, 2011 17:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe mal SpionAtoms Code genommen und anstelle des nachträglichen Tauschens einfach das Einfügen gleich an zufällige Positionen gepackt.

BlitzBasic: [AUSKLAPPEN]
width = 3
height = 3
Global count = width * height
Dim array(count)

;Gibt für n > 0 den Index des n-ten freien Feldes zurück
Function NthFreeField(n)
For i = 1 To count
If array(i)=0 Then n = n - 1
If n <= 0 Then Return i
Next
End Function

;Fülle das Feld
SeedRnd(MilliSecs())
For i = 0 To count-1
array( NthFreeField( Rand (1, count-i) ) ) = i+1
Next

;Anzeige geklaut von SpionAtom
Graphics 400, 400, 0, 2
SetBuffer BackBuffer()

fgb = GraphicsWidth() / width
fgh = GraphicsHeight() / height

For i = 0 To count - 1
Text (i Mod width + 0.5) * fgb, (i / width + 0.5) * fgh, array(i+1)
Next

Flip
WaitKey
End
MrKeks.net

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group