how to use the variable rand in c ++ and not repeat the number? [closed]

-1

Help I am doing a naval battle in c ++ and I have to face the user in front of the machine and I must use the rand function to generate a random coordinate within a 10x10 matrix, what do I do so that I do not repeat the same data? / p>     

asked by jc_delgado 19.06.2016 в 08:13
source

3 answers

5

To generate random numbers in C ++, you can use the random library, available from C ++ 11. This library allows you to create random numbers using different sets of generators and distributors (to distribute statistically the appearance of different numbers.) An example:

std::random_device rd; // Proporciona la semilla
std::mt19937 gen(rd()); // Generador aleatorio
std::uniform_int_distribution<> dis(1, 6); // Distribución uniforme
for(int n=0; n<10; ++n)
    std::cout << dis(gen) << ' ';
std::cout << '\n';

Why is not it advisable to use srand(time(NULL)) ? Because it is a mechanism that is potentially unsafe. It is an outdated and little random generator that can lead to security issues in our application.

On the other hand, in order not to repeat numbers, you only have the possibility of storing the results in a container. In this case, the most appropriate is set . Since set does not support duplicates, it becomes a good candidate:

std::set<int> datos;

do
{
  std::cout << "Introduce un número: ";
  int numero;
  std::cin >> numero;

  bool ok;

  // opción 1
  // insert retorna un pair.
  // El primer parámetro del pair es un booleano que indica si se ha hecho la
  // inserción y el segundo es un iterador al elemento.
  // tie es una función que permite extraer los elementos del pair y solo nos
  // quedamos con el primero, el segundo lo descartamos con std::ignore.
  std::tie(ok,std::ignore) = datos.insert(numero);

  // opción 2
  // primero comprobamos si ya existe el número y después lo insertamos
  // 
  ok = (datos.count(numero) == 0);
  datos.insert(numero);

  if( !ok )
    std::cout << "Número repetido" << std::endl;
} while( datos.size() < 10 );

Another possible solution is to generate a vector with all the possibilities, which in your case I imagine that there will be 100 possibilities. Then you mess up that vector to finally take out elements one by one (by the beginning or the end). When the messy vector is going you will get random squares without repetitions:

std::vector<int> datos(10);

// Rellenamos datos con números del 1 al 10
std::iota(std::begin(datos), std::end(datos), 1); 

std::cout << "Array ordenado: " << std::endl;  
for( auto i : datos )
  std::cout << i << " ";
std::cout << std::endl;

// mezclamos el array
std::random_device rd;
std::mt19937 g(rd());

std::shuffle(datos.begin(), datos.end(), g);

std::cout << "Array desordenado: " << std::endl;  
for( auto i : datos )
  std::cout << i << " ";
std::cout << std::endl;

Greetings.

    
answered by 19.06.2016 в 17:12
2

So that it does not generate the same number, you have to change the seed with which that number is generated, the easiest way is to use the current time.

with srand you are changing the seed. Add

srand (time(NULL));

before the rand () and you will have your numbers random.

    
answered by 19.06.2016 в 08:21
1

The response proposed by @ReymonARG is not correct since it does not guarantee that the generated numbers will not be repeated. The simplest thing is to save an auxiliary matrix of type bool in which you save which positions are valid and if you re-generate an existing data discard it.

Another option is to generate a vector with all possible positions and mix it with the random_shuffle function in the library algorithm .

    
answered by 19.06.2016 в 16:22