I'm looking to write a little dice game called Farkle (you may know it from Kingdom come delivarance) in C++ but I'm still learning, so I have some trouble with it.
atm I'm trying to roll 6 dice and put every rolled number in an array to be able to work with it afterwards. everything seem to work fine but Visual Studio ist outputting this error Code:
Run-Time Check Failure #2 - Stack around the variable 'die' was corrupted.
this is my code:
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
void dice() {
int die[5];
int i = 1;
while (i <= 6) {
die[i] = rand() % 6 + 1;
cout << die[i];
i++;
}
}
int main()
{
srand(time(NULL));
dice();
system("STOP");
return 0;
}
is ths actually the right approach for this kind of programm?
No, a better way to generate uniformly distributed random numbers would be
#include <random>
#include <algorithm>
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> d6(1, 6); // {1, 2, 3, 4, 5, 6} with equal probability
int die[5];
std::generate(die, die + 5, [&gen, &d6](){ return d6(gen); });
If you were generating multiple sets of 5d6, you can re-use the same gen rather than re-initialising it each time
As others pointed out. Your error stems from using a too small array. This post will be more about your code being more like C.
It is more idiomatic in C++ to use std::array instead of raw arrays.
Also it is recommended not to use rand() since it produces bad random numbers and by using the modulo operation you are introducing additional bias to you random numbers. Instead one should use the classes from the <random> header.
To make the code even more readable you could try to use the functions from the <algorithm> to replace you loops by named algorithms.
This leads to following code:
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <random>
void dice() {
std::array<int, 6> die;
std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<int> dice_roll{1, 6};
std::generate(begin(die), end(die), [&] { return dice_roll(gen); });
std::copy(begin(die), end(die), std::ostream_iterator<int>{std::cout});
}
int main() {
dice();
std::cin.get();
}
You have 2 problems in your code:
The size of your array is 5, but you access 6 indices (1 to 6), you can avoid this by changing the <= to < in the condition.
The indices of an array in C++ start with 0, but you start with 1. You can fix that if you change each die[i] to die[i-1] in your code.
Another approach (fixing both problems) would be to initialize i=0 and go with while (i < 5)
index i should be from 0 to 5, not 1 to 6.
It's obvious that when i = 6, it run out of the range of dice which made an error.
Edit these lines:
int i = 0;
while (i <= 5) {
....
Try this code :
#include <iostream>
#include <cstdlib>
#include <ctime>
void populateArray( int ar[], /*const*/ int n )
{
for( int i = 0 ; i < n ; ++i ) ar[i] = std::rand() % 50 + 1 ;
}
int main()
{
// http://en.cppreference.com/w/cpp/numeric/random/srand
std::srand( std::time(nullptr) ) ; // **** important ****
const int ARRAY_SIZE = 50;
int ar[ARRAY_SIZE] = {0} ;
populateArray( ar, ARRAY_SIZE ) ;
for( int v : ar ) std::cout << v << ' ' ;
}
Related
I want to use a while loop to generate a random number for a variable to spell out a scrambled word. My problem is that my code generates a number that is random but repeats that number rather than using a new number.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
string wordList[5] = {"cool", "friend", "helpful", "amazing",
"person"};
srand(time(0));
int rWord = rand() % 5 + 1;
string randWord = wordList[rWord];
int runs = 0;
int wordLen = randWord.length();
while(runs != wordLen){
int ranLN = rand() % wordLen;
char randLetter = randWord[ranLN];
cout << randLetter;
runs++;
}
return 0;
}
I expected my results to be a fully scrambled word, but I instead got repeated letters. For example, I got the word "friend" scrambled as "eennn".
As suggested in comments, the current range of rWord is 1,2,3,4,5 which must be fixed to 0,1,2,3,4.
Thus I removed +1 from it's initialization equation in the following answer.
In addition, ranLN can be duplicate thus you got repeated letters.
Then, a possible way is recursively shuffling all characters of randWord and output them after the while loop finished as follows.
The same algorithm is shown here as an example:
DEMO
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <utility>
int main()
{
std::string wordList[5] = {"cool", "friend", "helpful", "amazing", "person"};
srand(time(0));
std::size_t rWord = rand() % 5;
std::string randWord = wordList[rWord];
std::size_t runs = 0;
std::size_t wordLen = randWord.length();
while(runs != wordLen)
{
std::swap(randWord[runs], randWord[rand() % wordLen]);
++runs;
}
std::cout << randWord << std::endl;
return 0;
}
BTW, although rand() should be usually implemented by a something better LCG,
but, for instance as noted in (my local) C++ standard draft n4687, the algorithm used in rand() is completely compiler implementation defined:
29.6.9 Low-quality random number generation [c.math.rand]
int rand();
void srand(unsigned int seed);
... rand’s underlying algorithm is unspecified. Use of rand therefore continues to be non-portable, with unpredictable and oft-questionable quality and performance.
Fortunately, in C++11 and over, we can use <random> to generate a guaranteed quality randomness.
Thus I recommend you to use them with std::shuffle as follows.
If you need more high-quality randomness, you can use std::mt19937 instead of std::minstd_rand:
DEMO
#include <iostream>
#include <string>
#include <random>
#include <algorithm>
int main()
{
std::string wordList[5] = {"cool", "friend", "helpful", "amazing", "person"};
std::minstd_rand gen(std::random_device{}());
std::uniform_int_distribution<std::size_t> dis(0, 4);
std::size_t rWord = dis(gen);
std::string randWord = wordList[rWord];
std::shuffle(randWord.begin(), randWord.end(), gen);
std::cout << randWord << std::endl;
return 0;
}
In my humble opinion after generating all random words then using set data structure would make the random word unique.
Random function usually generates random numbers within a given range. But is it possible to randomly select from a pre-defined list? For example i have [1,4,5,6] and i want to randomly select from this list only. If so, how?
Thanks :)
P.s:: C++ code would help me a big deal ^^
The following code would help, instead of choose a random integer, we can choose a random index in the set;
int numbers[4] = {1,4,5,6};
srand (time(NULL));
int index = rand() % 4;
int number = numbers[index];
Here is a C++11 version utilizing <random> instead:
#include <random>
int numbers[4] = {1,4,5,6};
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0,3);
int index = distribution(generator); // generates number in the range 0..3
int number = numbers[index];
Good way to do that might be using shuffle. Basically, you shuffle array and then start to pick numbers one by one
#include <iostream> // std::cout
#include <algorithm> // std::shuffle
#include <array> // std::array
#include <random> // std::default_random_engine
int main () {
std::array<int, 4> foo {1,4,5,6};
std::shuffle(foo.begin(), foo.end(), std::default_random_engine(12345));
std::cout << "shuffled elements:";
for (int x: foo)
std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
Im currently having trouble generating random numbers between -32.768 and 32.768. It keeps giving me the same values but with a small change in the decimal field. ex : 27.xxx.
Heres my code, any help would be appreciated.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand( time(NULL) );
double r = (68.556*rand()/RAND_MAX - 32.768);
cout << r << endl;
return 0;
}
I should mention if you're using a C++11 compiler, you can use something like this, which is actually easier to read and harder to mess up:
#include <random>
#include <iostream>
#include <ctime>
int main()
{
//Type of random number distribution
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
//Mersenne Twister: Good quality random number generator
std::mt19937 rng;
//Initialize with non-deterministic seeds
rng.seed(std::random_device{}());
// generate 10 random numbers.
for (int i=0; i<10; i++)
{
std::cout << dist(rng) << std::endl;
}
return 0;
}
As bames53 pointed out, the above code can be made even shorter if you make full use of c++11:
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>
int main()
{
std::mt19937 rng;
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
rng.seed(std::random_device{}()); //non-deterministic seed
std::generate_n(
std::ostream_iterator<double>(std::cout, "\n"),
10,
[&]{ return dist(rng);} );
return 0;
}
Also, If you are not using c++ 11 you can use the following function instead:
double randDouble(double precision, double lowerBound, double upperBound) {
double random;
random = static_cast<double>(((rand()%(static_cast<int>(std::pow(10,precision)*(upperBound - lowerBound) + 1))) + lowerBound*std::pow(10,precision)))/std::pow(10,precision);
return random;
}
So, I think this is a typical case of "using time(NULL) isn't a great way of seeding random numbers for runs that start close together". There isn't that many bits that change in time(NULL) from one call to the next, so random numbers are fairly similar. This is not a new phenomena - if you google "my random numbers aren't very random", you'll find LOTS of this.
There are a few different solutions - getting a microsecond or nanosecond time would be the simplest choice - in Linux gettimeofday will give you a microsecond time as part of the struct.
It seams to be plainly obvious but some of the examples say otherwise... but i thought when you divide 1 int with another you always get an int? and you need to type cast each int to double/float before you divide them.
ie: double r = (68.556* (double)rand()/(double)RAND_MAX - 32.768);
also if you call srand() every time you call rand() you reset the seed which results in similar values returned every time instead of ''random'' ones.
I've added a for loop to your program:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
srand(time (NULL));
for (int i = 0; i < 10; ++i) {
double r = ((68.556 * rand () / RAND_MAX) - 32.768);
cout << r << endl;
}
return 0;
}
Example output:
31.6779
-28.2096
31.5672
18.9916
-1.57149
-0.993889
-32.4737
24.6982
25.936
26.4152
It seems Okay to me. I've added the code on Ideone for you.
Here are four runs:
Run 1:
-29.0863
-22.3973
34.1034
-1.41155
-2.60232
-30.5257
31.9254
-17.0673
31.7522
28.227
Run 2:
-14.2872
-0.185124
-27.3674
8.12921
22.4611
-0.414546
-21.4944
-11.0871
4.87673
5.4545
Run 3:
-23.9083
-6.04738
-6.54314
30.1767
-16.2224
-19.4619
3.37444
9.28014
25.9318
-22.8807
Run 4:
25.1364
16.3011
0.596151
5.3953
-25.2851
10.7301
18.4541
-18.8511
-0.828694
22.8335
Perhaps you're not waiting at least a second between runs?
Is there a function that generates k random numbers within a specified range.
For example I want 5 random numbers between 0 to 100, with or without replacement.
You could use std::generate_n with either rand() or a generator from the new C++11 random number generators.
There is the Boost library, which you can use to generate random numbers, for example.
The following code generates 5 random numbers from [0, 100] with replacement:
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
std::vector<int> result;
for (int i = 0; i < numWantedNumbers; ++i)
result.push_back(distribution(generator));
}
If you want to generate the numbers without replacement, simply check if they are
still available:
#include <algorithm>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
std::vector<int> result;
while (result.size() < numWantedNumbers)
{
int number = distribution(generator);
if (std::find(result.begin(), result.end(), number) == result.end())
result.push_back(number);
}
}
Note: The rejection sampling in the example without replacement has the obvious drawback that longer vectors are quite difficult to create. Just try to draw 99 out
of 100 numbers, to see what I mean (or even better draw 9999 out of 10000). If this
is a problem, I would suggest to create a random permutation of all possible numbers
and then cut the vector at the requested size:
#include <algorithm>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
// Generate a vector with all possible numbers and shuffle it.
std::vector<int> result;
for (int i = 0; i <= 100; ++i)
result.push_back(i);
for (int i = 0; i <= 100; ++i)
{
int x = distribution(generator);
std::swap(result[i], result[x]);
}
// Truncate to the requested size.
result.resize(numWantedNumbers);
}
Edit based on suggestion by juanchopanza:
In C++11 manner, the last variant would look like this
#include <algorithm>
#include <random>
#include <vector>
const int numWantedNumbers = 5;
int main()
{
std::random_device device;
std::mt19937 generator(device());
std::uniform_int_distribution<> distribution(0, 100);
// Generate a vector with all possible numbers and shuffle it.
std::vector<int> result;
for (int i = 0; i <= 100; ++i)
result.push_back(i);
std::random_shuffle(result.begin(), result.end());
// Truncate to the requested size.
result.resize(numWantedNumbers);
}
g++-4.6 compiles it happily, if you add the -std=c++0x switch.
Edit: Make use of std::random_shuffle() (tanks to James Kanze).
Yes there is a rand() function in C++ which can be used including cstdlib header file in your program.
You can implement your program using the following code.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int max {100};
int min {0};
int number;
int count = 5; //assuming that only 10 numbers we need to print
srand(time(0));
for(int i=1;i<=count;i++)
{
number = rand() % (max - min +1) + min;``
cout<<number<<endl;
}
}
Just like in Java , (Math . random * ) statement is there a way to input array numbers in C++ ?
For example I want to input numbers from 6 to 89 with RANDOM numbers in C++. Assign them into arrays.
I know how to sort the numbers but I would just like to know the method to do random numbers to make my life easier.
I am rusty in programming and I am open to any criticism but I would appreciate a straightforward response.
Use srand to seed the random number generator, then use rand to get a random number.
For example, the following program populates an array with rando values in your requested range:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main (void) {
int xyzzy[10];
// Seed the generator.
std::srand (time (0));
// Populate the array.
for (int i = 0; i < sizeof(xyzzy) / sizeof(*xyzzy); i++)
xyzzy[i] = 6 + (std::rand() % 84);
// Print the array.
for (int i = 0; i < sizeof(xyzzy) / sizeof(*xyzzy); i++)
std::cout << xyzzy[i] << "\n";
return 0;
}
This outputs (in my case):
59
51
84
83
58
85
83
25
50
22
Keep in mind that the properties of those random numbers may not be perfect due to the way they're generated but, unless you're a statistician or cryptographer, they should be fine.
In C++11
#include <random>
int main()
{
int arr[10] = {0};
std::mt19937 generator; // mersenne twister
std::uniform_int_distribution<> dist(6, 89);
for(int n=0; n<10; ++n)
{
arr[n] = dist(generator);
}
}
To get a random number from 6 - 89:
srand ( time(NULL) );
int randomNumber = 6 + rand() % (89 - 6 + 1);
#include <random>
#include <array>
#include <functional>
#include <boost/range/algorithm/generate.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
#include <iterator>
int main()
{
//Create an array
std::array<int, 10> arr;
//Fill the array
std::random_device gen;
boost::generate(
arr,
std::bind(
std::uniform_int_distribution<int>(6,89),
std::ref(gen)));
//Print the generated values
boost::copy(arr, std::ostream_iterator<int>(std::cout, "\n"));
}