How to forbid program to generate number if it's in vector list?

Hello world! I'm new here and new to C++ as well (doing online course for 4 days right now and tinkering with C++ in visual studio myself). I'm currently training my vector/loop skills and I've decided to create a program that would:
1. choose a random number
2. try to guess this number
3. count how many tries it did

And it all works. But the program can choose the same number several times which isn't perfect... I tried to add guesses to vector list and then order program to not choose any number that is already on vector list but it doesn't work/I don't know how.

This line is probably heresy: guess != (find(myVector.begin(), myVector.end(), guess) != myVector.end());

And one more thing - can I cout vector list without using for loop? If so, how? I would prefer to have results in this way: "results: a, b, c, d" than:
"results: a
results: b"
etc.

I attach the code below. Thank you for all suggestions! I would also love to hear if you have any suggestions related to my code, there are probably many things I could do more efficiently and I would love to learn them!
Thanks in advance

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <array>
#include <vector>
#include <algorithm>

using namespace std;

int main() {

	srand((unsigned int)time(NULL));
	
	vector<int>myVector(0);
	
	int number = rand() % 10;
	number < 10;
	int sum;
	sum = 1;
	int guess;


	for (int i = 0; i<10; myVector.push_back(guess))
	{
		
		guess = i + rand () %9;
		guess != (find(myVector.begin(), myVector.end(), guess) != myVector.end());
		cout << guess << endl;
		
		if (guess != number)
		{
			sum++;
			continue;
		}

		if (guess == number)
		{
			myVector.push_back(guess);
			cout << "number was " << number << endl;
			cout << "it took me " << sum << " tries." << endl;
			for (int val : myVector)
			{
				cout << "My guessess: " << val << endl;
			}
			break;
		}
	}
	return 0;

}
Last edited on
load a vector with the numbers you want, for this problem, 0-9. Then you can shuffle it and just go sequentially; it is now a random value in range with no duplicates. you can get fancy and fill it with iota() if you want to show off.

https://www.cplusplus.com/reference/algorithm/shuffle/
https://www.cplusplus.com/reference/numeric/iota/
after these ideas replace rand()%9 with your shuffled vector: guess = v[index++]
so if you shuffled 0,1,2,3,4 to randomly be 31042 it would produce the 'random' values 3, 1, 0, 4, 2 in that order, never duplicating. A side effect of this: the index is how many guesses you made, give or take an off by one count.

warning: line 18 is legal but does nothing at all.
best practice: initialize the value when you create it:
int sum{1}; //instead of int sum; sum = 1; or int sum = 1; prefer the {} approach
best practice: initialize everything: int guess{0};

you have to loop to print a vector.
consider
cout << "results: ";
for(...)
cout << vec[i] <<", "; //note how I padded spaces in the strings, you can do or not on that as you see fit to format the output.
after the for loop, do your cout << endl; and any finishing text.

there may be a better way to express line 28 but if it works, its fine. sometime you need a complex line here and there.

later, when you have more time, study <random>. rand() is from C and is best avoided but for now it will get the job done. you may want to call srand(time(0)); to ensure it uses different numbers every time you run it.
Last edited on
Hello itsjustmyshadow,

A few things I see right off:

srand((unsigned int)time(NULL));. This is fine and will work, but from C++11 on prefer to use srand(static_cast<unsigned int>(time(nullptr)));.

Also have a look at https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful A nice video explaining the problems with using "rand()".

Keep in mind that "rand" is a PRNG, (Pseudo Random Number Generator). And that true randomness will include duplicate numbers and clusters.

Next is vector<int>myVector(0);. I do not believe there is any difference from vector<int>myVector;. Both should create an empty vector of (0) zero size.

You should always initialize you variables and you can write int sum{ 1 }; and save your-self a line of code. I am also wondering if "sum" should start at (0) zero? I am also thinking that "sum" is not the best choice for this variable name. I seems misleading.

I will know more when I have a chance to run the code.

Andy

Thank you jonnin and Handy Andy for replies!
jonnin - I'll take a look at iota, it seems interesting.

The problem is that I don't think line 28 even works. I thought that it would prevent program from generating numbers that are already pushed into vector list but it keeps generating same numbers...

Handy Andy - thanks for your post! I'll look at video you posted soon, I'm very interested in RNG.

Thank you both for your suggestions regarding int's!
Perhaps consider:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <random>
#include <vector>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <limits>
#include <iterator>

int main()
{
	constexpr size_t maxno {100};
	std::mt19937 rng(std::random_device {}());
	std::uniform_int_distribution<size_t> distrib(0, maxno);
	std::vector<size_t> randnos;

	for (char again {'y'}; again == 'y'; ) {
		auto rn {distrib(rng)};

		while (std::find(randnos.begin(), randnos.end(), rn) != randnos.end())
			rn = distrib(rng);

		randnos.push_back(rn);
		//std::cout << rn << '\n';

		std::cout << "I have thought of a unique random number between 0 and " << maxno << '\n';
		std::cout << "Please guess this number\n";

		size_t guesses {1};

		for (; ; ++guesses) {
			size_t ans {};

			while ((std::cout << "Enter guess " << guesses << ": ") && (!(std::cin >> ans) || ans > maxno)) {
				if (!std::cin) {
					std::cin.clear();
					std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
					std::cout << "That was not a number!\n";
				} else
					std::cout << "Number not in range 0 to " << maxno << '\n';
			}

			if (ans == rn) {
				std::cout << "Congrats! You have guessed correctly!\n";
				break;
			} else
				std::cout << "Sorry. That guess was not correct. try again\n";
		}

		std::cout << "You took " << guesses << " guesses\n";

		std::cout << "Guess another number (y/n) : ";
		std::cin >> again;
	}

	std::cout << "The guessed numbers are:\n";

	std::copy(randnos.begin(), randnos.end(), std::ostream_iterator<size_t>(std::cout, " "));
	std::cout << '\n';
}

Last edited on
Hello itsjustmyshadow,


The problem is that I don't think line 28 even works.


It does work a little bit, I think, but you do not do anything with it to make use of it, i.e., like picking another number.

Then there is the line guess = i + rand () %9;. You start by generating a number (0 - 9), but here you generate a number (0 - 8) and then add "i" to it. This would cause the "guess" to be larger than "number", which can only be a maximum of 9.

A start for now. I need to look at the find function closer.

Andy
Hello itsjustmyshadow,

Here is a start:
1
2
3
4
5
//if (guess == (find(myVector.begin(), myVector.end(), guess) != myVector.end()))
if (find(myVector.begin(), myVector.end(), guess) != myVector.end())
{
    std::cout << "\n    Match in vector!\n\n";
}

This is a start, but I was thing a while loop and not the if statement.Then inside the while loop you would generate a new number until there is no longer a match to anything in the vector.

I left the original line so you can see the difference and maybe understand why it does not work. Partly because you are checking an "int" against an "iterator" which are not the same types.

Andy
As per my code above......
@seeplus,

My fault. Either I did not refresh or just missed it.

As much as I enjoy reading your code and learning. I find it rather presumptuous to assume that OP has learned about "random", "numeric" and "iterator" header files.

I thought the give away is the "rand" and "srand".

Andy
Using <random> in C++ is far easier for generating general 'random' numbers than using rand()/srand() as you specify the type/range of the generated random number. Once you know the 2 line incantation (and the associated one for real distribution) .... Different ranges can also be defined with different names. For non-special statistical analysis, this is probably all that many coders need to know about <random>.

If the OP didn't know previously about any aspect of code, then what isn't understood can be looked up - or a specific question asked. IMO reading and understanding other code is a valid way of enhancing knowledge/understanding.
Last edited on
Topic archived. No new replies allowed.