# [C++]Zufallszahlen : Problem



## Guillermo (12. Mai 2008)

Hallo Leute,

ich habe ein kleines Problem, und zwar generiere ich durch einen Code Zufallszahlen, aber komischerweiße sind das immer die gleichen, und das will ich natürlich nicht, kann mir jemand weiterhelfen?

Ich habe diese Funktion hier, und die wird in main() dann 3 mal hintereinander aufgerufen, habe sie als test mal hier ausgeben lassen, damit ich sehe welche es sind, und es sind immer die gleichen Paare...


```
void zufallskoordinaten(void) {
     srand(time(NULL));
     int xKoordinate=rand()%5+1;
     int yKoordinate=rand()%5+1;
     cout << xKoordinate << yKoordinate << " ";
}
```


----------



## KD3 (12. Mai 2008)

```
#include <iostream>

void zufallskoordinaten() {
    srand(rand()*rand());
     int xKoordinate=rand()%5+1;
     int yKoordinate=rand()%5+1;

     std::cout << "X :" << xKoordinate << " Y :" << yKoordinate << "\n";
}


int main() {

    for(int i = 0; i < 50; i++) zufallskoordinaten();
    getchar();
    EXIT_SUCCESS;
    return 0;
    }
```

Funktioniert doch eigentlich schon gut. Was möchtest du denn am Ende damit machen? Ein Programm das Graphen oder so zeichnet?


----------



## Guillermo (12. Mai 2008)

Danke für deine Antwort, mal sehen ob es klappt...
Ne nicht wirklich, da aber kann man das machen Wie denn ? ^^
Die Funktion ist für ein kleines Konsolenspiel, und zwar Schiffe versenken


----------



## Guillermo (12. Mai 2008)

Aber noch eine Frage warum muss man den srand(rand()*rand()) schreiben?
Außerdem geht das nur wenn ich davor noch ein srand(time(0)) schreibe, sonst gibt er wieder die gleichen aus


----------



## KD3 (12. Mai 2008)

> Aber noch eine Frage warum muss man den srand(rand()*rand()) schreiben?



Logisch gesehen ist es sinnlos, genauso wie rand()%5+1. Sogesehen könnte es auch so aussehen:


```
#include <iostream>
#include <math.h>

void zufallskoordinaten(void) {
    int x1 = rand();
    srand(rand()*10000);
    int x2 = rand();

    x1 = round(x1%5) < 1 ? 1 : x1%5;
    x2 = round(x2%5) < 1 ? 1 : x2%5;

    std::cout << "X :" << x1 << " Y :" << x2 << "\n";
}


int main() {

    for(int i = 0; i < 50; i++) zufallskoordinaten();
    getchar();
    EXIT_SUCCESS;
    return 0;
    }
```


----------



## devDevil (13. Mai 2008)

Mein Gott ... wenn man keine Ahnung hat 


```
#include <iostream>
#include <cstdio>
#include <ctime>
#include <utility>

typedef std::pair <unsigned int, unsigned int> coordinate_t;

void init_random();
inline const coordinate_t random_coordinate();

int main() 
{
    init_random();
    
    for (unsigned char i(0); i < 50; ++i)
    {
        coordinate_t const& coord(random_coordinate());
        std::cout << "X: " << coord.first << " Y: " << coord.second << "\n";
    }
    
    return EXIT_SUCCESS;
}

void init_random()
{
    static bool ready(false);
    if (ready == false) { std::srand(static_cast<unsigned>(std::time(NULL))); read = true; }
}

inline const coordinate_t random_coordinate()
{ return std::make_pair(static_cast<unsigned int>((5 + 1) * std::rand() / (RAND_MAX + 1.0)), static_cast<unsigned int>((5 + 1) * std::rand() / (RAND_MAX + 1.0))); }
```
 wenn du jetzt init_random benutzt ... kannst du es von mir aus so oft tun wie du willst  Hab da mal ne Sperre reingebaut, damit es nur einmal die Initialisierungsfunktion aufruft 

Zu Zufällen: http://cplus.kompf.de/artikel/random.html


----------



## Guillermo (13. Mai 2008)

Hä ich check des überhauptnet was du da gemacht hast ^^
Ich will einfach eine Zahl zwischen 1 und 5, das sollte ja auch gehen, aber irgendwie nimmt er auch die 6 mit ich weiß auch nicht, warum, ichbenützte diese funktion hier : 


```
int Spieler::Zufallszahl(void)
{
    return rand()%5+1;
    }
```

Die is halt dann in der klasse drin und wird dann in einer anderen Funktion der klasse "Spieler" aufgerufen in dieser Funktion steht dann auch das srand(time(0)) drin, aber irgendwie wills nicht so richtig funktionieren


----------



## devDevil (13. Mai 2008)

Nein das srand hat in deinen Funktionen NICHTS zu suchen! Es sei denn du machst das so wie ich es mit init_random dir verdeutlichen wollte. Es darf nur EIN Mal aufgerufen werden. Dann ließ dir bitte mal den Link durch, den ich dir auch gepostet habe. Durch Module-Operator zu begrenzen ist nicht wirklich das Richtige ...


----------



## Guillermo (13. Mai 2008)

Ja, ich habs auch schon mit diesen Methoden versucht, es geht aber auch nicht, und ich habe es auch schon damit versucht indem ich das srand() nicht in eine funktion geschrieben habe, sondern in die mainfunktion, da hat es dann aber auch nicht geklappt, immer habe ich eins mehr bekommen als ich wollte, und durch das modulo wird ja nur das Gleichgewicht der Verteilung gestört, das ist mir eigentlich egal


----------



## Teambeta (14. Mai 2008)

devDevil hat gesagt.:


> Nein das srand hat in deinen Funktionen NICHTS zu suchen! Es sei denn du machst das so wie ich es mit init_random dir verdeutlichen wollte. Es darf nur EIN Mal aufgerufen werden. Dann ließ dir bitte mal den Link durch, den ich dir auch gepostet habe. Durch Module-Operator zu begrenzen ist nicht wirklich das Richtige ...



Ich darf srand so oft aufrufen wie ich lustig bin, nur ob es dann den Zweck erfüllt den ich will, nämlich Zufallszahlen die sich nicht ständig ähneln.

@Topic:

http://www.c-plusplus.de/forum/viewtopic-var-t-is-172876.html

Les dir das mal durch


----------



## Guillermo (14. Mai 2008)

Hat auch nix gebracht  , hab das alles schon versucht hab schon zig Sachen versucht aber es  geht einfach nicht ...
Kann mir denn niemand helfen?


----------



## devDevil (14. Mai 2008)

WAS soll daran nicht klappen? srand mit der aktuellen Zeit aufrufen (in main 1x), dann bekommst du "Zufalls"-Zahlen ...


----------



## Guillermo (14. Mai 2008)

Nein, es geht nicht, ich benutzte dann eben die von euch gegebenen Formeln aber ich bekomme dann imer Zahlen von 1-6 und nicht von 1-5 , ich weiß auch nicht warum, und wenn ich z.B das +1 weglasse, dann bekomme ich Zahlen von 0-6 ich dreh echt gleich durch , sitzt schon 2  Wochen daran ...


----------



## devDevil (14. Mai 2008)

So. Letztes mal freundlich:
Bitte lese dir durch, was man dir schreibt und beachte auch weiterführende Links.


```
#include <cstdlib>

namespace random
{
    inline const int rand(const int min, const int max)
    { return min + static_cast<int>((max - min + 1) * std::rand() / (RAND_MAX + 1.0)); }

    void init(const unsigned seed)
    { static bool ready(false); if (ready == false) { std::srand(seed); ready = true; } }
}; // utility
```
 Das rufst du dann einfach auf:


```
#include <iostream>
#include <ctime>
 
int main()
{
    random::init(static_cast<unsigned>(std::time(NULL)));
 
    for (unsigned char i(0); i < 50; ++i)
        std::cout << "X: " << random::rand(1, 5) << " Y: " << random::rand(1, 5) << "\n";

    return EXIT_SUCCESS;
}
```
 ... so . fertig.


----------



## Guillermo (14. Mai 2008)

Danke für deine Hilfe, wenn du mir aber nicht erklärst was du da machst dann nützt es mir auch nichts, ich will ja nicht , dass es einfach nur funktioniert, sondern ich will es auch verstehen ...


----------



## Guillermo (14. Mai 2008)

Hab jetzt erneut dein Programm benützt,  es geht nicht, als 2.Koordinate wird immer 6 gewählt, obwohl ich als Intervall 1 bis 5 angegeben habe...


----------



## devDevil (15. Mai 2008)

Ich erklär es dir nicht, weil du einfach den VERDAMMTEN Link lesen sollst statt hier 1000x das selbe zu fragen ohne dich mal ein Bisschen selbst zu bemühen. Das ist einfach nur dreist!


----------



## Guillermo (15. Mai 2008)

Das System selbst verstehe ich ja , auch dass du eine Sperre eingebaut hast und so find ich gut, aber ich verstehe nicht was das mit "inline" ist und so ...
Glaub mir, ich hab nicht nur einen Link angesehen, hab ziemlich viele Seiten angeschaut  zum Thema ZUfallszahlen, habe schon alles Möglichkeiten durch, kann das nicht sein, dass das irgendwas damit zu tun hat , dass ich eine Klasse benutzte? Vielleicht benutzte ich sie ja falsch.
Fakt ist ich "programmiere" ein Spiel, und zwar Schiffe Versenken, bin kein Profi deshalb probiere ich mich an kleineren Projekten aus,  ich poste hier nochmal den ganzen Code vielleicht kann ja einer von euch den Fehler erkennen...
Die Zufallszahlen brauche ich für die "künstliche Intelligenz" , damit der PC praktisch den echten Spieler beschießt...

Die für euch relevanten Funktionen sind Zufallszahl() und FeldBesetzten() in der mein Funktion ist dann die srand Funktion:


```
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

class Spieler {
      private:
              int Zufallszahl(int,int);
              char Feld[5][5];
      public:
             void ZeigeFeld(void);
             void Wasser(void);
             int schiffe;
             char typ; // p für pc // r  für real
             void TypErkennen(void);
             void FeldBesetzten(void);
      };

int main() {
    
    srand(static_cast<unsigned>(time(NULL)));
    
    Spieler spieler;
    spieler.schiffe=0;
    spieler.typ='r';
    
    Spieler pc;
    pc.schiffe=0;
    pc.typ='p';
    
    //Schiffsanzahl ausgeben
    cout << spieler.schiffe; 
    cout << pc.schiffe;
    
    
    /*spieler.Wasser();
    spieler.FeldBesetzten();
    spieler.ZeigeFeld();*/
    
    pc.Wasser();
    pc.FeldBesetzten();
    pc.ZeigeFeld();
    
    
    cout << endl << endl;
    system("pause");
    return 0;
    
}

void Spieler::TypErkennen(void) {
                   if (typ=='r') cout << "Realer Spieler";
                   if (typ=='p') cout << "Kuenstliche Intelligenz";
                   }
                   
void Spieler::Wasser() {
     for (int y=1;y<=5;y++) {
         for (int x=1;x<=5;x++) {
             Feld[x][y]=' ';
             }
         } 
     }
     
void Spieler::ZeigeFeld(void) {
     if (typ=='r') {
                   for (int y=1;y<=5;y++) {
                       cout << "\n";
                       for (int x=1;x<=5;x++) {
                       cout << "[" << Feld[x][y] << "]";
             }//Ende forschleife2
         } //Ende forscheleife1
                   }//ENDE IF
     
     if (typ=='p') {
                   //Computerfeldausgeben
                    for (int y=1;y<=5;y++) {
                       cout << "\n";
                       for (int x=1;x<=5;x++) {
                       cout << "[" << Feld[x][y] << "]";
                       }//Ende forschleife2
                    } //Ende forscheleife1
                   
                   }//Ende if
     }
     
void Spieler::FeldBesetzten(void) {
     if (typ=='r') {
                   for(int i=1;i<=5;i++) {
                   int x,y;
                   cout << "x:";cin >> x;
                   cout << "y:";cin >> y;
                   Feld[x][y]='S';
                   }//ende for schleife
                   }
                   
     if (typ=='p') {
                   int x,y;
                   
                   for(int a=1;a<=5;a++) {
                   x=Zufallszahl(1,5);
                   
                   x=Zufallszahl(1,5);
                   cout << x << y;
                   
                   if(Feld[x][y]==' ') Feld[x] [y]='S';
                   //else FeldBesetzten();
                                          
                   //} //Ende Forschleife
                   
                   }
                   }
                   
                   }
int Spieler::Zufallszahl(int min,int max) {
    
    return min + static_cast<int>((max - min + 1) * rand() / (RAND_MAX + 1.0));
    
    }
```


----------



## devDevil (15. Mai 2008)

Also .... ich schreib dir das gleich mal noch um. Aber du hast da einen grundlegenden Fehler ... kann sein das es daran liegt.

Ein Array hat einen Index von 0 ... size - 1. array[size] ist nicht definiert!

D.h. müssen deine Schleifen lauten:

```
for (unsigned char x(0); x < 5; ++x)
```
 ...


----------



## devDevil (15. Mai 2008)

```
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>


class Player
{
    static const std::size_t field_size;
    
public:
    enum type_t
    {
        ai = 0,
        real
    };

private:
    unsigned char m_field[field_size][field_size];
    unsigned int m_ships;
    std::string m_name;
    type_t m_type;

public:
    Player(std::string const& name, type_t const& type = real)
        : m_type(type), m_name(name), m_field(), m_ships(0)
    {}

    friend std::ostream& operator<<(std::ostream& out, Player const& data)
    { return out << "Spieler: " << data.m_name << "(" << data.show_type(out) << ")\n" << data.show_field(out); }

public:
    std::ostream& show_field(std::ostream& out) const
    {
        for (unsigned char x(0); x < Player::field_size; ++x)
        {
            for (unsigned char y(0); y < Player::field_size; ++y)
                out << "[" << m_field[x][y] << "]";
            out << "\n";
        }
        return out;
    }

    std::ostream& show_type(std::ostream& out) const
    { return out << (m_type == ai ? "PC" : "Person"); }
    
public:
    inline void reset_field()
    { std::memset(m_field, 0, sizeof(unsigned char) * Player::field_size * Player::field_size);    }
    
    void get_position()
    {
        std::size_t x(0);
        std::size_t y(0);

        if (m_type == real)
        {
            std::cout << "X-Koordinate: ";
            std::cin >> x;
            std::cout << "Y-Koordinate: ";
            std::cin >> y;
        }
        else // type == ai
        {
            x = random_position(0, Player::field_size - 1);
            y = random_position(0, Player::field_size - 1);
        }

        if (m_field[x][y] == ' ')
            m_field[x][y] = 'S';
        else
            get_position();
    }

private:
    inline const std::size_t random_position(const std::size_t min, const std::size_t max) 
    { return min + static_cast<int>((max - min + 1) * std::rand() / (RAND_MAX + 1.0)); }
};

const std::size_t Player::field_size = 5;
```
 ... das ist die Klasse ... 


```
int main() 
{
    std::srand(static_cast<unsigned>(std::time(NULL)));
    
    std::vector<Player> players;
    players.push_back(Player("Detlev"));
    players.push_back(Player("Dieter", Player::ai));

    std::copy(players.begin(), players.end(), std::ostream_iterator<Player>(std::cout, "\n"));
   
    players[0].get_position();
    players[1].get_position();
    
    std::copy(players.begin(), players.end(), std::ostream_iterator<Player>(std::cout, "\n"));

    std::cin.ignore();    
}
```
 so wird se benutzt


----------



## Guillermo (15. Mai 2008)

Uff da sind ziemlich viele neue Sachen drin


----------

