-1

I'm trying to create a random generation of numbers using two ranges of numbers. For example :

value = rand() % 13 + 1;
suit = rand() % 4 + 1;
cout<<cardd<<color<<endl;

This is a piece of the program I'm using, I want to create from four colors of cars, 13 models. Is there any way to remove duplicates? Thanks.

guasabito
  • 1
  • 3
  • Could you clarify what you mean by "duplicates"? – Max Vollmer Jun 10 '18 at 23:58
  • Possible duplicate: https://stackoverflow.com/questions/23049748/how-to-make-random-numbers-unique or https://stackoverflow.com/questions/41560927/inserting-unique-random-numbers-into-a-vector – Galik Jun 11 '18 at 00:25
  • With those numbers you could fill a vector with all possible combinations and remove them as needed. – Galik Jun 11 '18 at 00:31
  • 4
    Instead of trying to remove duplicates, why don't you just [`std::shuffle`](http://en.cppreference.com/w/cpp/algorithm/random_shuffle) a bunch of cards and pick the first few? – eesiraed Jun 11 '18 at 01:00

3 Answers3

0

You may store the values in a std::set, or simply erase duplicates from a vector:

std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
0

I don't understand your actual problem. But I can do something for eliminating duplicates in random numbers.

First, the next two lines are problematic:

value = rand() % 13 + 1;
suit = rand() % 4 + 1;

because rand() % M can't generator the complete range of random numbers in [0,M-1]. The real reason is that rand() is generates a random number in [0,INT_MAX], but INT_MAX sometimes can't divide M exactly.

If you don't want to use <random> like above. You can modify it a little.

  value =((double)rand())/INT_MAX * 13 ;
  suit = ((double)rand())/INT_MAX*4;

Finally I suggest std::default_random_engine and uniform_int_distribution, like the following:

static std::default_random_engine e(time(0));
uniform_int_distribution u(1,13);

unordered_set<int> numbers;
int number;
do
{
   number=u(e);
}while(numbers.find(number)!=numbers.end());
numbers.insert(number);

I just mean you can use unordered_set<int> to record the generated numbers, and to avoid duplicates.

user1118321
  • 25,567
  • 4
  • 55
  • 86
hongyu xiao
  • 229
  • 1
  • 7
0

I would suggest using a pair, then you can compare each new pair to a vector of pairs:

First create the vector:

vector<pair<int,int>> deck;

Then inside your loop, create cards:

pair <int,int> card;
card.first = ((double)rand())/INT_MAX * 13;
card.second = ((double)rand())/INT_MAX*4;

Then use binary_search to add only non-duplicates to the deck:

if(!binary_search(deck.begin(), deck.end(), card)){
  deck.push_back(card);
}

Here is a working prototype that probably suits your needs:

#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>

int main()
{
    srand(time(0));
    std::vector <std::pair<int,int>> deck;
    for(int n = 0;n < 52;n++){
        std::pair <int,int> card;
        card.first = ((double)rand())/INT_MAX * 13;
        card.second = ((double)rand())/INT_MAX*4;
        if(!binary_search(deck.begin(), deck.end(), card)){
            deck.push_back(card);
            std::sort(deck.begin(), deck.end());
            std::cout << "\n" << card.first << " " << card.second;
        }else{
            std::cout << "\ndiscarding duplicate: " << card.first << " " << card.second;
            n--;
        }
    }
}

But Fei Xang's idea to just create a deck and shuffle it makes more sense.