This question already has an answer here:
-
Why does rand() yield the same sequence of numbers on every run?
6 answers
I just finished coding a Minesweeper type game, and everything's good except for that each time I run the application, it generates the same number (I ran it 3 different times, saved the output to 3 text files and used the diff
command in Linux, it didn't find any differences). It's seeded by time(NULL)
so it should change every time, right?
Here's my code:
main.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Minesweeper/box.h"
#include <cstdio>
int main(int argc, char** argv){
using namespace std;
bool gameOver = false;
int x, y, score = 0;
const int HEIGHT = 10;
const int WIDTH = 10;
unsigned int Time = time(0);
cout << "Welcome to Minesweeper. " << endl;
//setup grid
Box grid[10][10];
for(int i = 0; i < WIDTH; i++)
for(int n = 0; n < HEIGHT; n++){
unsigned int value = rand() %100 + 1;
cout << value << endl;
if(value <= 38){
grid[i][n].setFill(MINE);
//cout << i << "," << n << " is mined." << endl;
}
else
grid[i][n].setFill(EMPTY);
}
for(int r = 0; r < WIDTH; r++)
for(int l = 0; l < HEIGHT; l++)
if(grid[r][l].getFill() == EMPTY)
cout << r << "," << l << " - EMPTY." << endl;
else if (grid[r][l].getFill() == MINE)
cout << r << "," << l << " - MINE." << endl;
while(!gameOver){
cout << "Enter coordinates (x,y): ";
scanf("%i,%i",&x,&y);
if(grid[x][y].getFill() == MINE)
gameOver = true;
else{
cout << "Good job! (You chose " << x << "," << y << ")" << endl;
score++;
}
}
cout << "You hit a mine! Game over!" << endl;
cout << "Final score: " << score << endl;
getchar();
return EXIT_SUCCESS;
}
It's seeded by time(NULL)
If it is, I can't see it. In fact, a search for it in your code returns nothing. The default behaviour, if you don't explicitly seed, is the same as if you had seeded it with the value 1.
You need to explicitly state something like:
srand (time (NULL));
at the start of main
somewhere (and make sure you do this once and once only).
Though keep in mind this makes it dependent on the current time - if you start multiple jobs in the same second (or whatever your time resolution is), they'll start with the same seed.
From the C standard (on which C++ is based for these compatibility features):
The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.
You need to seed randomizer. Call srand()
at the beginning.
To add to the answers by others, you can use the Mersenne Twister Algorithm, which is a part of the C++11 library. Its fast becoming a standard in many common softwares to generate random numbers.
For example, this is the function I wrote, which I use often to generate random numbers in my other codes:
std::vector<double> mersennetwister(const int& My,const int& Mz,
const int& Ny,const int& Nz)
{
int ysize = (My + 2*Ny + 1);
int zsize = (Mz + 2*Nz + 1);
int matsize = ysize*zsize;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// Seeding the generator with the system time
std::mt19937_64 generator (seed);
// Calling the Mersenne-Twister Generator in C++11
std::uniform_real_distribution<double> distribution(0,1);
// Specifying the type of distribution you want
std::vector<double> randarray(matsize,0);
// Saving random numbers to an array
for (int i=0;i<matsize;++i)
{
randarray[i] = distribution(generator); // Generates random numbers fitting the
// Distribution specified earlier
}
return(randarray);
}
Bottomline: C++11 has some excellent features for numerical operations and it would be a good idea to look into them. As for the Mersenne Twister, http://en.wikipedia.org/wiki/Mersenne_twister