Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

spacegaier

Alter Hase

  • »spacegaier« ist der Autor dieses Themas

Beiträge: 572

Beruf: Student

  • Private Nachricht senden

1

22.06.2006, 20:18

Random-Algorithmus

Hi,

habe folgendes Problem:

Will in einem Fenster an zufällig generierten Stellen Rechtecke mit einer zufälligen Farbe zeichnen lassen. Dies geht soweit auch.

ABER: Die Farbe ist fast gleich, wie die vorhergehende und die Position des Rechtecks wird einfach immer nur etwas weitergeschoben. Kennt ihr einen guten Algorithmus damit die Zufallszahlen "zufälliger" werden?

mfg spacegaier

PS: der "schlechte" Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void bigrect::RandomColor()
{
    srand((unsigned)(time(NULL)));              //Zufallsgenerator aktivieren

    b_color_r = rand()%256;                     //RGB-Farbwerte generieren

    b_color_g = rand()%256;                     //            ""

    b_color_b = rand()%256;                     //            ""

}

void bigrect::CalculateRect()
{
    RECT    b_mainrc;                           //Rect für den Clientbereich


    GetClientRect(hWnd,&b_mainrc);              //Größe des Clientbereich holen


    srand((unsigned)(time(NULL)));              //Zufallsgenerator aktivieren

    int b_x_iPosition = rand()%b_mainrc.right;  //einen x-Wert aus der Breite des Clientbereich generieren

    int b_y_iPosition = rand()%b_mainrc.bottom; //einen y-Wert aus der Höhe des Clientbereich generieren


    b_rc_to_draw.top        = b_y_iPosition;
    b_rc_to_draw.left       = b_x_iPosition;
    b_rc_to_draw.bottom     = b_y_iPosition + b_height;
    b_rc_to_draw.right      = b_x_iPosition + b_width;
}

Anonymous

unregistriert

2

22.06.2006, 20:25

Irgendwo mal im Netz gefunden:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const unsigned int random(
   const unsigned int lo,
   const unsigned int hi)
{
   // number of different values

   const unsigned int diff = hi - lo + 1;

   // determine shift distance

   unsigned int v = diff-1;
   unsigned int c = 15;
   if (diff>1) {
       --c;
       while (v >>= 1) --c;
   }

   unsigned int r;

   do
   {
       // shift random number to the right

       r = rand() >> c;
   } while (r>=diff);
   // repeated until small enough


   // add lower bound

   return r + lo;
}

...

int zahl = random(0,9999);
Keine Garantie auf lauffähigkeit, und co.

spacegaier

Alter Hase

  • »spacegaier« ist der Autor dieses Themas

Beiträge: 572

Beruf: Student

  • Private Nachricht senden

3

22.06.2006, 20:30

Danke, werd ihn mal testen.

spacegaier

Alter Hase

  • »spacegaier« ist der Autor dieses Themas

Beiträge: 572

Beruf: Student

  • Private Nachricht senden

4

22.06.2006, 20:36

Der ist sehr gut. Hab aber immer noch ein, dass ich vorher schon hatte. Es werden in dem Fenster ca. 8 Rechtecke gezeichnet, doch dann kommen nur noch weiße Rechtecke und zwar über den ganzen Bildschirm (nicht das Fenster) verteilt!!!

Hab ich in meinem Code irgendwo einen Fehler eingebaut, was die Rechteckposition und die Anzahl der Rechtecke anbelangt?

//EDIT: Wenn ich den Positionsgenerator mit nix da's Code betreibe wird ein paar Sekunden lang korrekt in das Fenster gezeichnet. Dann aber werden wie gesagt alle Rechtekce weiß und werden auf die obere, rechte Ecke des Bildschirms gezeichnet und zwar auf einem Bereich, der so groß ist wie das Fenster. Es scheint so, als ob das Handle sich ändert, oder?

mfg spacegaier

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

5

23.06.2006, 08:57

Du darfst srand nur einmal aufrufen!

spacegaier

Alter Hase

  • »spacegaier« ist der Autor dieses Themas

Beiträge: 572

Beruf: Student

  • Private Nachricht senden

6

23.06.2006, 14:23

Ich rufe srand gar nicht mehr auf. Ich habe alle srand durch den random-Code von nix da ersetzt.

Das Problem ist aber das gleiche wie vorher. Oder darf ich den neuen Code auch nur einmal aufrufen? Wenn ja, wie kann ich dann mehrere Generatoren erstellen?

Muss ich nix da's-Code dann in eine Klasse packen und dann von dieser mehrere Instanzen aufrufen, die dann den Wert für jeweils eine meiner Variabeln generieren?

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

23.06.2006, 16:07

Also einmal musst du schon noch srand aufrufen...
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

spacegaier

Alter Hase

  • »spacegaier« ist der Autor dieses Themas

Beiträge: 572

Beruf: Student

  • Private Nachricht senden

8

23.06.2006, 17:52

??? Ich will ja aber mehrere Zahlen generieren (die drei Farbvariabeln, die Poisitonen). Wie mache ich das dann mit nix da's Code?

Hier mein momentaner Code

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void smallrect::RandomColor()
{
                    
        s_color_r = random(0,254);                  //RGB-Farbwerte generieren

        s_color_g = random(0,254);                  //            ""

        s_color_b = random(0,254);                  //            ""

}

void smallrect::CalculateRect()
{
    RECT    s_mainrc;                               //Rect für den Clientbereich

    
    GetClientRect(hWnd,&s_mainrc);                  //Größe des Clientbereich holen

    
    int s_x_iPosition = random(0,s_mainrc.right);   //einen x-Wert aus der Breite des Clientbereich generieren

    int s_y_iPosition = random(0,s_mainrc.bottom);  //einen y-Wert aus der Höhe des Clientbereich generieren

    
    s_rc_to_draw.top        = s_y_iPosition;
    s_rc_to_draw.left       = s_x_iPosition;
    s_rc_to_draw.bottom     = s_y_iPosition + s_height;
    s_rc_to_draw.right      = s_x_iPosition + s_width;
}


mfg spacegaier

Black-Panther

Alter Hase

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

9

23.06.2006, 18:35

Also irgenwie seh ich da nirgends srand()???

Zur Erklärung... Die rand-Funktion ist ja nur ein "PseudoZufallsgenerator", d.h. er muss initialisiert werden, und ausgehend, von dieser Zahl, werden dann die "Zufallszahlen" ausgegeben... Initialisieren tut man ihn mit srand(EineAusgangszahl); Hierbei verwendet man meist die Zeit, weil sie bei jedem Aufruf anders ist...
Danach kann man rand ganz "normal" verwenden!
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

10

24.06.2006, 07:44

Also, so wie du das zu füllende Rechteck berechnest, kannst du auch Rechtecke basteln, die aus dem Fenster rausragen. Das ist aber vermutlich nicht das Problem.

Ob du seed () nun einmal oder gar nicht aufrufst, ist auch nicht das Problem, weil der Zufallszahlengenerator immer Zahlen produzieren kann, die für deine Zwecke hinreichend zufällig sind. Da der Generator von nix da auch blos die rand () Funktion benutzt musst du also auch gar nichts anderes machen.

Ich fürchte eher, dass dein Problem an der Stelle auftritt, an der du die Rechtecke zeichnen willst.

So und nun schweife ich mal ein wenig ab, weil die Funktionsweise eines Zufallszahlengenerator vermutlich nichts mit dem Problem in deiner Rechteck-Füllfunktion zu tun hat. :D

Hier nochmal die generelle Funktionsweise eines Pseudo-Zufallszahlengenerator:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <time.h>
#include <iostream>

int p1 = 17;  // grosse Primzahl

int p2 = 13;  // andere grosse Primzahl

int seed = 0; // Startwert des Generators


int my_rand ()
{
    int r = (seed + p1) % p2; // Naechsten Wert berechnen

    seed = r;                 // als neue Quelle merken

    return r;
}

void my_seed (int s)
{
    seed = s; // Manuell einen neuen Startwert erzeugen

}

int _tmain(int argc, _TCHAR* argv[])
{
    my_seed (time (NULL));

    // Die ersten 13 Werte sind "zufaellig" und alle Zahlen

    // in [0, 12] kommen vor. Dann wiederholt sich die

    // Reihenfolge wieder...

    for (int i = 0; i < 15; ++i)
        std::cout << my_rand () << ' ';

    getchar ();
}

Der Generator ist natürlich ziemlich grottig (weil nicht besonders zufällig...), aber er beschreibt das Prinzip ersmal recht gut. ;)

Was passiert also:

Erst wird der Generator initialisiert, damit er nicht für jeden Programmlauf die selbe Zahlenfolge produziert. Hier nimmt man die aktuelle Zeit, weil die vermutlich hinreichend zufällig ist. Das macht man aber nur einmal, weil die produzierte Folge sonst nur so zufällig ist, wie die "Seeds," was bei der Zeit ein wenig ausgeprägter Faktor ist. 8)

Dann wird immer aus dem letzen Seed ein neuer Wert berechnet, der hinterher der neue Seed wird. So bekommt man immer einen anderen Wert, bis der Zyklus einmal durchlaufen ist. Bei einer echten rand () Funktion ist der natürlich deutlich länger als die 13, die mein Zyklus erzeugt.

MfG
Rainer
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

Werbeanzeige