vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Brandneu! sevEingabe v3.0 - Das Eingabecontrol der Superlative!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 15:45

Hallo,

ich habe ein Control, welches mir ein kariertes Feld zeichnet. Die Größe der zu zeichnenden Felder kann ich auch individuell bestimmen. Jetzt habe ich es so gemacht, dass wenn ich auf eines dieser Felder klicke das gesamte Feld ausgefüllt wird, also mit einer anderen Farbe übermalt wird. Entsprechende Funktionen habe ich alles schon fertig. Jetzt möchte ich aber zufällig einige Felder ausmalen lassen, also ohne, dass ich vorher darauf klicken muss.

Hier erstmal der Code, wie ich den habe:
   Private Function GetFieldIndex(ByVal x As Integer, ByVal y As Integer) As _
     Integer
      ' Errechnet den Index des Feldes (von links nach rechts)
      Return (Me.Width \ FieldSize.Width) * (GetLineFromField(y) - 1) + _
        GetColumnFromField(x) - 1
   End Function
 
   Private Function GetFieldPosition(ByVal x As Integer, ByVal y As Integer) As _
     Point
      ' Errechnet aus den X- und Y-Koordinaten die Zeilen- und Spaltennummer
      Return New Point(GetColumnFromField(x), GetLineFromField(y))
   End Function
 
   Private Function GetFieldRectangle(ByVal x As Integer, ByVal y As Integer) _
     As Rectangle
      ' Errechnet aus der X- und Y-Koordinate das entsprechende Rechteck
      Dim width As Integer = FieldSize.Width - 1
      Dim height As Integer = FieldSize.Height - 1
 
      Return New Rectangle((x \ FieldSize.Width) * FieldSize.Width, (y \ _
        FieldSize.Height) * FieldSize.Height, width, height)
   End Function
 
   Private Function GetFieldRectangle(ByVal FieldPosition As Point) As Rectangle
      ' Errechnet aus der Zeilen- und Spaltennummer das entsprechende Rechteck
      Dim width As Integer = FieldSize.Width - 1
      Dim height As Integer = FieldSize.Height - 1
 
      ' X und Y Koordinaten mit 1 subtrahieren, damit das Raster nicht 
      ' überzeichnet wird
      Return New Rectangle((FieldPosition.X - 1) * FieldSize.Width, ( _
        FieldPosition.Y - 1) * FieldSize.Height, width, height)
   End Function
 
   Private Function GetColumnFromField(ByVal x As Integer) As Integer
      ' Spalte berechnen und mit 1 addieren (verhindert null-basierte Spalte)
      Return x \ FieldSize.Width + 1
   End Function
 
   Private Function GetLineFromField(ByVal y As Integer) As Integer
      ' Zeile berechnen und mit 1 addieren (verhindert null-basierte Zeile)
      Return y \ FieldSize.Height + 1
   End Function
 
   Private Sub Field_Paint(ByVal sender As System.Object, ByVal e As _
     System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
      ' Berechne, wie viele vertikalen Linien gezeichnet werden können
      For i As Integer = 0 To Me.Width \ FieldSize.Width
         ' Vertikale Linie zeichnen
         e.Graphics.DrawLine(New Pen(pLineColor), i * FieldSize.Width - 1, 0, i _
           * FieldSize.Width - 1, Me.Height)
      Next
 
      ' Berechne, wie viele horizontalen Linien gezeichnet werden können
      For i As Integer = 0 To Me.Height \ FieldSize.Height
         ' Horizontale Linie zeichnen
         e.Graphics.DrawLine(New Pen(pLineColor), 0, i * FieldSize.Height - 1, _
           Me.Width, i * FieldSize.Height - 1)
      Next
 
      ' Anzahl der Einheiten (Felder) zeichnen
      For i As Integer = 0 To pUnits.Length - 1
         ' Rechteck zum ausfüllen berechnen und zeichnen
         e.Graphics.FillRectangle(New SolidBrush(pUnits(i).Color), _
           GetFieldRectangle(pUnits(i).Position))
      Next
   End Sub
 
   Private Sub Field_MouseClick(ByVal sender As System.Object, ByVal e As _
     System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseClick
      ' Überprüfe, ob jede Einheit (Feld) im Array gezeichnet wurde
      If pUnitsSet < pUnits.Length Then
         ' Wenn nicht, dann die Position für nächste Einheit (Feld) festlegen
         pUnits(pUnitsSet).Position = GetFieldPosition(e.X, e.Y)
         ' Zähler um 1 erhöhen
         pUnitsSet += 1
 
         ' Zu zeichnendes Rechteck neuzeichnen lassen
         Me.Invalidate(New Region(GetFieldRectangle(e.X, e.Y)))
      End If
   End Sub
Dabei ist pUnit ein Array von Objekten vom Typ Unit. Diese beinhalten eine Eigenschaft Position, welches die Zeilen- und Spaltennummer beinhaltet, wo dieses gezeichnet werden soll und eine Eigenschaft Color, die die entsprechende Farbe beinhaltet. Color ist hierbei aber unwichtig.

Wie kann ich also nun nach Zufallsprinzip diese Felder zeichnen lassen? Allerdings soll es nur auf der linken Hälfte des gesamten Controls passieren! Ich brauche also eine Funktion, die die Felder auf der linken Hälfte des Controls nach Zufallsprinzip ausmalt. Dabei kann die Anzahl aber variieren, also die Größe des Arrays pUnits. Vielleicht sollte die Funktion auch überprüfen, ob überhaupt soviele freie Felder dafür vorhanden sind. Bei Bedarf kann ich das Control auch in ein neues Projekt packen und als Archiv irgendwo hochladen (wobei das hier schon fast alle Methoden sind).

Danke schonmal
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: errt
Datum: 20.09.08 16:54

Ich denke, ein sinnvoller Ansatz wäre, alle Felder auf der entsprechenden Seite in einer Schleife durchzugehen (bzw. alle Felder durchgehen und dann jeweils prüfen ob das aktuelle Feld auf der entsprechenden Seite ist) und immer wenn eine Zufallszahl < als ein festgelegter Wert (zwischen 0 und 1) ist, das Feld auszumalen. Der festzulegende Wert ist dann der zu erwartende Anteil ausgemalter Felder.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 17:08

Also die Indizes der erlaubten Felder in ein Array packen (Funktion zum ermitteln des Index habe ich ja) und das dann durchlaufen. Dazu einen Wert von 0 und 1 und 1 heißt in dem Sinne beispielsweise Feld ausfüllen. Soweit klar. Allerdings fehlt mir der Ansatz, wie ich die erlaubten Felder in ein Array packen kann. Also ich weiß nicht, wie ich die erlaubten Indizes ermittle, ob die auf der richtigen Seite sind...
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: FlyingEagleLW
Datum: 20.09.08 18:40

das hängt doch davon ab wie und ob du zählst und in welcher richtung

*1
[0] [1] [2] [4]
[5] [6] [7] [8]
 
oder
 
*2
[0] [2] [4] [6]
[1] [3] [5] [7]
bei *1: zwei schleifen, die erste geht waagerecht, die zweite senkrecht. zuerst mal weißt du ja wieviele in einer reihe sind. damit die hälfte ermitteln (das ist alle_waagerecht / 2 danach dann immer nur bis zur hälfte alle waagerechten durchgehen, pack die dann einfach in ein array und zufallsgenerator drüber wie ert schon sagte.

bei *2: wäre es ähnlich wie in 1, nur das du da die beiden schleifen vertauschen müsstest.

Beitrag wurde zuletzt am 20.09.08 um 18:40:52 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 19:30

Danke für eure Hilfe. Jetzt habe ich eine Lösung gefunden. Das war sogar ziemlich einfach, wenn man erstmal drauf kommt
      Dim leftArray As New List(Of Point)
      Dim leftWidth As Integer = CInt(Math.Ceiling(GetColumnFromField(Me.Width _
        - 2) / 2))
      Dim leftHeight As Integer = GetLineFromField(Me.Height - 2)
 
      For i As Integer = 0 To leftHeight
         For j As Integer = 0 To leftWidth
            leftArray.Add(New Point(i, j))
         Next
      Next
 
      For i As Integer = 0 To leftArray.Count - 1
         Debug.WriteLine(leftArray(i).ToString)
      Next
Bei mir ist übrigens 1. der Fall. Meine Indizes sind von links nach rechts angeordnet. Da ich jetzt ein Point-Objekt habe kann ich das in einen Index umrechnen. Ich muss ja meine vorhande Funktion nur noch ein wenig umschreiben, damit es ein Objekt vom Typ Point entgegennimmt. Dann sollte das klappen.
Vielleicht brauch ich den Index auch gar nicht. Ich glaube mit dem Point-Objekt kann ich mehr anfangen. Nochmal kurz drüber nachdenken. Danke jedenfalls für die Denkanstöße.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 19:44

Habe allerdings noch eine Frage. Wieviele Felder ausgefüllt werden soll ist ja vorgegeben, kann aber auch variieren. Wie kann ich die Zufallswerte nun so vergeben, dass auch wirklich genau diese Anzahl gezeichnet wird, also mit einer 1 gekennzeichnet werden und alle anderen mit einer 0? Es muss im Endeffekt die Anzahl der vergebenen 1 mit der Anzahl der auszufüllenden Felder übereinstimmen. Wie mache ich das?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: errt
Datum: 20.09.08 20:42

Ich würde den Anteil der zu färbenden so wählen, dass zu erwarten ist, dass die gewünschte Anzahl Felder gefüllt wird. Dann in der Schleife mitzählen wieviele gefüllt wurden. Ist die Zahl erreicht, wieviele gefüllt werden sollen, brichst du die Schleife ab. Ist am Ende der Schleife die Zahl noch nicht erreicht, gehst du die Schleife nochmal durch. Hat nur den Nachteil dass wahrscheinlich mehr ausgefüllte Felder im oberen Bereich gefüllt werden als im unteren.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 20:45

Das dachte ich mir auch schon, aus dem von dir genannten "Problem" wollte ich das nicht machen. Allerdings habe ich mir überlegt: Wenn ich die Liste mit den erlaubten Feldern irgendwie mische, also so, dass alle Elemente nicht mehr logisch aneinander gereiht sind, dann kann ich einfach in einer Schleife den Wert auf 1 setzen und kann das auch ganz leicht überprüfen, ob die Anzahl schon erreicht wurde. Allerdings finde ich keine Funktion zum mischen der einzelnen Array Elemente Hat vielleicht jemand was dazu?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 22:48

Also.. ich habe das nun soweit, dass zufällig in einem bestimmten Bereich Felder ausgemalt werden. Allerdings variiert die Anzahl, obwohl immer 5 gefüllt werden sollten. Manchmal sind es 5, manchmal auch nur 4 oder gar 3.
[code Public Sub SetRandom()
' Array erstellen
Dim leftSideArray As List(Of Point) = LeftSide()

' Array mischen
ShuffleArray(leftSideArray, 7)

' Anzahl der Einheiten durchlaufen
For i As Integer = 0 To pUnits.Length - 1
' Eigenschaft der Einheit setzen
pUnits(i).Position = leftSideArray(i)

' Anzahl gesetzter Einheiten erhöhen
pUnitsSet += 1

' Entsprechenden Bereich neu zeichnen
Me.Invalidate(New Region(GetFieldRectangle(pUnits(i).Position)))

Debug.WriteLine(leftSideArray(i))
Next
End Sub

Private Function LeftSide() As List(Of Point)
' Array deklarieren
Dim leftArray As New List(Of Point)
' Hälfte der Felder der Breite ermitteln
Dim leftWidth As Integer = CInt(Math.Ceiling(GetColumnFromField(Me.Width - 2) / 3))
' Höhe ermitteln
Dim leftHeight As Integer = GetLineFromField(Me.Height - 2)

' Alle verfügbaren Felder in die Liste aufnehmen
For i As Integer = 0 To leftHeight
For j As Integer = 0 To leftWidth
leftArray.Add(New Point(i, j))
Next
Next

Return leftArray
End Function

Private Sub ShuffleArray(ByRef arrayToBeShuffled As List(Of Point), ByVal numberOfTimesToShuffle As Integer)
Dim rndPosition As New Random(DateTime.Now.Millisecond)

For i As Integer = 1 To numberOfTimesToShuffle
For i2 As Integer = 1 To arrayToBeShuffled.Count
swap(arrayToBeShuffled(rndPosition.Next(0, arrayToBeShuffled.Count)), arrayToBeShuffled(rndPosition.Next(0, arrayToBeShuffled.Count)))
Next i2
Next i
End Sub

Private Sub swap(ByRef arg1 As Point, ByRef arg2 As Point)
Dim strTemp As Point = arg1
arg1 = arg2
arg2 = strTemp
End Sub]Damit habe ich das versucht, aber irgendwie scheint das nicht ganz zu funktionieren. Ich bin mal mit dem Debugger durchgegangen und jede Einheit bekommt eine Position zugewiesen und sollte auch angezeigt werden, aber irgendwie gehts nicht. Hoffe jemand findet den Fehler.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Lösung: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 20.09.08 23:22

Ich hatte einen kleinen Fehler beim erstellen meiner Liste für die linke Seite erlaubter Zeichen. Da gibts Positionen mit einer 0, was in dem Control außerhalb des sichtbaren Bereiches ist. Habe also dafür gesorgt, dass das nicht mehr passiert. Ergo meine ganzen Probleme sind gelöst. Danke für die Hilfen
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Lösung: Zufällige Rechtecke im Control ausmalen 
Autor: FlyingEagleLW
Datum: 21.09.08 02:07

bitte schön, gern geschehen.

Tip: quellcode in die code-blöcke packen

aber ich hätte da noch ne idee ohne das array "zu mischen" ...

du gehst durch die von mir beschriebenen schleifen und sammelst alle felder als feld(+index o.ä.) in einem array (alle die meinetwegen links sind) und nimmst danach x-zufallszahlen, die als untergrenze die untergrenze und als obergrenze die obergrenze des array haben. dann sollte es auch eine ausgewogene verteilung geben (insofern der randomizer mitspielt . wenn du die felder als elemente/objekte in deinem array hast und diese z.b. als klassen/objekte ansprechbar sind sollte das relativ simpel sein. wobei mit array eine collection gemeint ist.

würde mich aber mal interessieren was genau du da eigentlich proggst, falls du uns das verraten kannst/darfst/willst.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Lösung: Zufällige Rechtecke im Control ausmalen 
Autor: keco
Datum: 21.09.08 13:31

Das mit dem Code war ein Unfall... habe mich beim reinkopieren irgendwie verklickt :x

Danke noch für deinen Ansatz, aber ich hatte mit dem Randomizer schonmal das Problem, dass der ständig gleiche Zahlen ausgespruckt hatte, weil das irgendwie viel zu schnell ging, mit einem Sleep dazwischen wars wenigstens durcheinander, aber naja. Möchte das nicht riskieren. Und jetzt, wo ich schon die FUnktion habe zum mischen und auch mit dem Ergebnis zufrieden bin, möchte ich nicht weiter drin rumrühren.

An sich sind eigentlich nicht alle Felder ansprechbar, also möglich ist es schon, aber die brauche ich nicht ansprechen, sondern nur die ausgefüllten. Im Endeffekt soll das eigentlich eine Art Spielfeld darstellen, wobei die ausgefüllten Felder die Spielfiguren sind. Deswegen brauche ich auch nur die Spielfiguren auswählen und nicht die einzelnen Felder. Deswegen gibt es nur ein Array mit den Spielsteinen. Wird auf das Spielfeld geklickt werden die Pixel-Koordinaten in meine Feld-Koordinaten umgerechnet und mit der Position-Eigenschaft der einzelnen Spielsteine verglichen. Ist eine Übereinstimmung dabei wird die Eigenschaft SelectedUnit eben mit dem ausgewählten Stein gesetzt.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Lösung: Zufällige Rechtecke im Control ausmalen 
Autor: FlyingEagleLW
Datum: 21.09.08 14:32

den randomizer kann man imho auch mit parametern starten, wo man dann z.b. die aktuelle zeit übergibt und man dann dadurch etwas "zufälligere" zahlen erhält.

aber wenn es so funktioniert wie du dir das vorstellst ist ja alles prima.
am ende entscheidet ja ohnehin meistens das ergebnis und nicht nur der weg. letzterer ist nur bei zeitkritischen geschichten interessant(er). musst halt mal gucken ob mein ansatz oder dein ansatz am ende in diesem punkt schneller wäre.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel