Not truly Random - c++

For some reason the code I'm about to post below is not purely random... And I have used srand(), to attempt to make it random.. I don't know why it's acting weird...
#include<vector>
#include "../Header Files/SinglePlayer.h"
SinglePlayer::SinglePlayer()
{
}
int myRand(int low, int high)
{
srand(time(NULL));
return rand() % (high - low + 1) + low;
}
void SinglePlayer::startGame()
{
cout << "Starting Single Player........." << endl;
cout << "Starting out with two cards...." << endl;
int randomCardStarterOnePlayer = myRand(0,10);
int randomCardStarterTwoPlayer = myRand(0,10);
int randomCardStarterOneAI = myRand(0,10);
int randomCardStarterTwoAI = myRand(0,10);
this -> calculateRandomStarter(randomCardStarterOnePlayer,
randomCardStarterTwoPlayer,
randomCardStarterOneAI,
randomCardStarterTwoAI);
cout << "You Start out with " << amountPlayer << endl;
cout << "Computer Starts out with " << amountAI << endl;
}
void SinglePlayer::calculateRandomStarter(int randomOnePlayer, int randomTwoPlayer, int randomOneAI, int randomTwoAI)
{
amountPlayer = amountPlayer + randomOnePlayer + randomTwoPlayer;
playerCards.push_back(randomOnePlayer);
playerCards.push_back(randomTwoPlayer);
amountAI = amountAI + randomOneAI + randomTwoAI;
AICards.push_back(randomOneAI);
AICards.push_back(randomTwoAI);
}
SinglePlayer::~SinglePlayer()
{
}
Outcome:
~~~~~~~~~~BLACKJACK~~~~~~~~~~~
Do you want to play single player, or multiplayer? (Enter 0 for single
player, 1 for multiplayer)
0
Starting Single Player.........
Starting out with two cards....
You Start out with 2
Computer Starts out with 2
You can see the player and computer starts with same number.. and that always happens for some reason... I cant seem to spot the problem, please help.

time(NULL) returns time in seconds, and because you set new seed every time you are generating new number you probably (in most cases) set same number as seed every time.
Move:
srand(NULL)
to start of main or somewhere where it will be called only once.

It sounds like time(NULL) in your code returns something that is constant and does not call std::time(NULL) as you may expect. If it did, you would have a random number properly generated from rand().
Try to print the output of time(NULL) and check if you actually get the number of seconds elasped since the epoch. If not, make sure you include <ctime> and call fully qualified srand(std::time(NULL)).

Related

timestamp of time(0) at multiple places in a C++ program

Why is the timestamp of time(0) at multiple places in a C++ program the same value?
Ex:
int main(){
cout << time(0) << endl;
cout << time(0) << endl;
cout << time(0) << endl;
cout << time(0) << endl;
}
All of the values above are the same. Is this because the program is executed at such a fast speed that the time values in the above example are all the same?
Could someone help me out? Thanks!
The resolution of the time() function isn't fine grained enough to result in different values to make a different result for each call you make, i.e. the CPU is faster.
You might try to insert std::this_thread::sleep_for calls to check what timing resolution fits for your needs with the hardware and OS you have at hand.
The time(0) function returns the current time in seconds.
The code that you upload will run all the code in one second.
Therefore, even if the time is output, all the same time is output.
The following code is to output the current time continuously for 3 seconds.
If you run it, you will see a lot of numbers, but if you look closely you can see that the number changes three times.
#include <iostream>
#include <ctime>
int main()
{
time_t s = std::time(0); // time_t is int64 in windows 10 64bit.
time_t n;
do {
n = std::time(0);
std::cout << n << " ";
} while ((s + 3) > n); // repeat until 3 sec passed.
return 0;
}

Random Generator Help C++ [duplicate]

This question already has answers here:
How to generate different random numbers in a loop in C++?
(13 answers)
Closed 7 years ago.
I'm having trouble with a random generator.
I'm trying to print out random values and I'm getting almost the same value every single time.
This is what I have:
void Deck::shuffle() {
StackNode<Card>* top = stack->top;
for (int i = 0; i < stack->numNodes - 1; i++) {
int x = random(i);
StackNode<Card>* temp = findCard(x);
//cout << "Random index was: " << random(i) << endl;
//cout << "Face value of random was: " << temp->data.getFaceVal() << endl;
cout << "Top: " << top->data.getFaceVal() << endl;
cout << "Temp: " << temp->data.getFaceVal() << endl;
swapX(top,temp);
}
}
Here's my random generator function:
int random(int index) {
int r;
srand(time(NULL));
cout << "Index: " << index << endl;
r = rand() % 50;
cout << "Random value: " << r << endl;
return r;
}
I think you can use std::shuffle here for your problem. Like this:
#include <vector>
#include <algorithm>
void Deck::shuffle() {
StackNode<Card>* top = stack->top;
std::vector<StackNode<Card>*> cards;
for (int i = 0; i < stack->numNodes - 1; i++) {
cards.push_back(findCard(i))
}
std::shuffle(cards.begin(), cards.end());
for (auto card : cards) {
std::cout << card->data.getFaceVal() << std::endl;
}
}
By the way, I would recommend you to call srand only once in your code.
rand() is a pseudo random number generator. The numbers it generates appear to be random, but they are generated by a completely deterministic function. The seed that you give it with sand() determines the starting point for the function. If you give it the same seed it will generate the same sequence of random numbers. You can try this and see for your self by seeding with a literal, like srand(200) and running the program several times, you will get the exact same results.
If you want different results each time you have to seed with something that will be different each time the program runs, so time is often used as a seed. In your case you are in a very tight loop so many of the calls in a row use the same time value.
If you call srand() once, before your loop this problem will go away.

c++ using random numbers to decide the next encounter

EDITED for full code
I am trying to make a text based rpg game because im really bored and want to put my c++ "skills" at test xd.
But i am having a problem with the functions srand and rand, the function to generate random numbers.
What i want do achieve, is to let the RNG decide the next action of the game. I.e :
#include <iostream>
#include <windows.h>
#include <string>
#include "conio.h"
#include <time.h>
using namespace std;
void GetRandom();
int main()
{
int x;
string name;
srand(time(NULL));
cout << "welcome to adventurers world!" << endl;
cout << "you wake up on an island far far away and you don't know where you are" << endl;
Sleep(2000);
cout << "Please enter the name of your adventurer" << endl;
getline(cin, name);
cout << "hello " << name << endl;
Sleep(1000);
cout << "where would you like to go, " << name << " ?" << endl;
Sleep(1000);
cout << "1. waddle around the beach\n2. go to the cave straight ahead\n3. go into the forest" << endl;
cin >> x;
if(x==1)
{
cout << "you waddle abit around on the beach, and you suddenly " << random;
}
_getch();
}
void random()
{
srand(time(NULL));
int randnumber = rand() % 2 + 1;
randnumber = randnumber;
if(randnumber == 1)
{
cout << "you encounter a mudcrab" << endl;
}
else if (randnumber == 2)
{
cout << "you find a stick" << endl;
}
}
What i want do achieve here is, if the random number generated is 1 do (randnumber == 1) and if it is 2, do (randnumber == 2)
but instead it just gives me a hexidecimal as output.
is my code properly written? am i using the right expression for srand, calculation w/e.
And is this even possible to do? or do i have to write it out manually what will happen next, which wont make it as much a dynamic game.
thanks for your help and time
At the moment, you're not calling the function random, you're displaying its address. Try this:
if(x==1)
{
cout << "you waddle abit around on the beach, and you suddenly ";
random();
}
Don't seed the random generator with the time each time you need a random number. Unless the usage is a long time between (more than a second), that will set the seed to the same value.
Don't name your function random(). That will make the random() function inaccessible. It probably should be choose_random_object() or something like that.
Seed the random number generator once when the program begins, and only reseed it if you need to repeat the random numbers (unlikely in a situation such as this).
Calling a function should return a value which is useful—which yours is not. Call a procedure (a function which does not return a value) for its side-effects, such as printing out a word.
Here's what your code should look like. The comments give an explanation of the changes.
srand(time(NULL)); // srand() needs only to be called once in the beginning.
if(x == 1)
{
cout << "you waddle abit around on the beach, and you suddenly ";
GetRandom(); // call the function to output what you need.
}
void GetRandom() // change the name of the function.
{
int randnumber = rand() % 2 + 1;
// no need for: randnumber = randnumber;
if(randnumber == 1)
{
cout << "you encounter a mudcrab" << endl;
}
else // no need for else if since the random # cannot be anything else but 2
{
cout << "you find a stick" << endl;
}
}

Working with timers

I am trying to create a timer where it begins with a certain value and ends with another value like.
int pktctr = (unsigned char)unpkt[0];
if(pktctr == 2)
{
cout << "timer-begin" << endl;
//start timer here
}
if(pktctr == 255)
{
cout << "timer-end" << endl;
//stop timer here
//timer display total time then reset.
}
cout << "displays total time it took from 1 to 255 here" << endl;
Any idea on how to achieve this?
void WINAPI MyUCPackets(char* unpkt, int packetlen, int iR, int arg)
{
int pktctr = (unsigned char)unpkt[0];
if(pktctr == 2)
{
cout << "timer-begin" << endl;
}
if(pktctr == 255)
{
cout << "timer-end" << endl;
}
return MyUC2Packets(unpkt,packetlen,iR,arg);
}
Everytime this function is called unpkt starts from 2 then reaches max of 255 then goes back to 1. And I want to compute how long it took for every revolution?
This will happen alot of times. But I just wanted to check how many seconds it took for this to happen because it won't be the same everytime.
Note: This is done with MSDetours 3.0...
I'll assume you're using Windows (from the WINAPI in the code) in which case you can use GetTickCount:
/* or you could have this elsewhere, e.g. as a class member or
* in global scope (yuck!) As it stands, this isn't thread safe!
*/
static DWORD dwStartTicks = 0;
int pktctr = (unsigned char)unpkt[0];
if(pktctr == 2)
{
cout << "timer-begin" << endl;
dwStartTicks = GetTickCount();
}
if(pktctr == 255)
{
cout << "timer-end" << endl;
DWORD dwDuration = GetTickCount() - dwStartTicks;
/* use dwDuration - it's in milliseconds, so divide by 1000 to get
* seconds if you so desire.
*/
}
Things to watch out for: overflow of GetTickCount is possible (it resets to 0 approximately every 47 days, so it's possible that if you start your timer close to the rollover time, it will finish after the rollover). You can solve this in two ways, either use GetTickCount64 or simply notice when dwStartTicks > GetTickCount and if so, calculate how many milliseconds were from dwStartTicks until the rollover, and how many millseconds from 0 to the result of GetTickCount() and add those numbers together (bonus points if you can do this in a more clever way).
Alternatively, you can use the clock function. You can find out more on that, including an example of how to use it at http://msdn.microsoft.com/en-us/library/4e2ess30(v=vs.71).aspx and it should be fairly easy to adapt and integrate into your code.
Finally, if you're interested in a more "standard" solution, you can use the <chrono> stuff from the C++ standard library. Check out http://en.cppreference.com/w/cpp/chrono for an example.
If you want to use the Windows-API use GetSystemTime(). Provide a struct SYSTEMTIME, initialize it properly and pass it to GetSystemTime():
#include <Windows.h>
...
SYSTEMTIME sysTime;
GetFileTime(&sysTime);
// use sysTime and create differences
Look here for GetSystemTime() there is a link for SYSTEMTIME there, too.
I think boost timer is the best solution for you.
You can check the elapsed time like this:
#include <boost/timer.hpp>
int main() {
boost::timer t; // start timing
...
double elapsed_time = t.elapsed();
...
}

Program is generating same random numbers on each run? [duplicate]

This question already has answers here:
Why does rand() yield the same sequence of numbers on every run?
(7 answers)
Closed 5 years ago.
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