Limit selection of random positions in a two-dimensional array

3

I'm doing a minesweeper that should have size 10 * 10 and within this I must locate 10 mines in random positions.

My problem is that when generating the random positions, these are, in some cases, repeated and therefore overwritten. That is, if in the 3rd round of the loop it takes the position (3,7) and then it takes the same position in the 5th round, the value is overwritten and therefore a mine is deducted.

How can I avoid repeating positions?

Here is the part of the code where the problem is:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define size 10
int main()
{
    srand(time(NULL));
    int i=0;
    int j=0;
    int count=0;
    int bombs=0;
    int x=0;
    int map[size][size];
    for(x=0; x<size; x++) //crea las minas
    {
        i=rand()%11;
        j=rand()%11;
        map[i][j]=1;
        bombs++;
    }
    for (i=0; i<size ; i++ )
        for (j=0; j<size ; j++ )
            if(map[i][j]==1)
            {
                count++;
            }
    printf("bombs = %d\n",count);//verifica la cantidad de bombas
    for(i=0; i<size; i++)//imprime el array
    {
        for(j=0; j<size; j++)
            printf("%d",map[i][j]);
        puts("");
    }
    return 0;
}
}
    
asked by David Urbina 16.09.2017 в 04:02
source

3 answers

2

Because you do not check the position inside the matrix before assigning the pump to know if it is empty otherwise it generates a new coordinate until the position is empty.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FILAS 10
#define COLUMNAS 20

int main()
{
srand(time(NULL));
int i=0;
int j=0;
int count=0;
int bombs=0;
int x=0;
int map[FILAS][COLUMNAS];
int numOfBoms = 15; // Numero de bombas a crear

// Inicializamos el array
for (i=0; i < FILAS; i++ )
    for (j=0; j < COLUMNAS; j++ )
      map[i][j]=0;
/*
for(x=0; x<numOfBoms; x++) //crea las minas
{
    i = (rand()%10) + 1;
    j = (rand()%10) + 1;;
    map[i][j]=1;
    bombs++;
}*/

puts("Generacion de bombas");
while (bombs < numOfBoms)
{
    i = (rand() % FILAS);
    j = (rand() % COLUMNAS);

    //  Verificacion de posición  
    if (map[i][j] == 0)
    {
      map[i][j] = 1;
      bombs++;
      printf("Bomba %d en: %d:%d\n", bombs, i, j);
    }
}
puts("");

for (i=0; i < FILAS; i++ )
    for (j=0; j < COLUMNAS; j++ )
        if(map[i][j] == 1)
            count++;

printf("Conteo de bombs = %d\n  ", count); // verifica la cantidad de bombas
for (i = 0; i < COLUMNAS; i++)
  printf("%*d", 3, i);
puts("");

for(i = 0; i < FILAS; i++)//imprime el array
{
    printf("%d ", i);
    for(j = 0; j < COLUMNAS; j++)
      printf("%*d", 3, map[i][j]);

    puts("");
}

return 0;
}

Add several variables to control the size of the board using Rows and Columns and the number of mines to generate.

You can see the compiled code in link

    
answered by 16.09.2017 в 05:50
2

The easiest way (in my opinion):

  • We use a map of char .

  • We create the map of 1 single dimension. char[100] has the elements in the same relative position as char[10][10] .

  • We map the map with '.' (points). memset( ) does it for us, without the need for loops or anything.

  • Before putting the bomb, we check if the map position already has a .

  • The result is something like this:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h> // Para 'memset( )'.
    
    #define SIZE 10
    #define BOMBS 10
    
    int main( void ) {
      int bombs = BOMBS + 1;
      char map[SIZE * SIZE];
      int pos;
    
      srand( time( NULL ) );
    
      // Inicializamos el array con puntos '.'.
      memset( map, '.', SIZE * SIZE );
    
      // MIENTRAS queden bombas sin esablecer.
      while( --bombs ) {
        // Repetimos HASTA que en el lugar NO HAY bomba.
        do {
          pos = rand( ) % ( SIZE * SIZE );
        } while( map[pos] == 'X' );
    
        // NO HAY bomba en esa posición. La ponemos.
        map[pos] = 'X';
      }
    
      // Mostramos el tablero.
      for( pos = 0; pos < ( SIZE * SIZE ); pos += SIZE )
        // SABEMOS que las filas son de longitud fija.
        printf("%.*s\n", SIZE, map + pos );
    
      return 0;
    }
    

    Code in Ideone: link

    Note : The use of char is to facilitate showing the board. A char admits values from 0 to 127 at least, so we have enough to store the number of free contiguous squares. Or a representation in bits of the state of said adjacent boxes.

        
    answered by 16.09.2017 в 05:51
    2

    You have the following errors :

    • Where you supposedly create mines, what you do is generate 10 random pairs of [ i , j ] that will represent 10 cells and put bombs in those cells, but the rest of the cells do not assign any value , so its content will be garbage (in fact when executing your program you can see this since many cells have values different to 0 and 1).

    • There is a problem that you mention that you can overwrite a mine if the same pair is generated randomly [ i , j ].

    • You count the number of pumps twice (with count and bombs ) which is redundant, this should not be necessary.

    I recommend you do it in the following way :

  • Create your matrix.
  • Fill in your 0 matrix.
  • Walk through each cell of your matrix and according to a certain probability assign a 1, this way it is as if you are placing bombs randomly on your board.
  • In the case of assigning a pump in the current cell you add 1 to bombs .
  • Repeat from step 2 until you have a board with the number of bombs you want.
  • You print your board.
  • According to the steps mentioned above, make the following changes to your code.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define size 10
    
    int main() {
        srand(time(NULL));
    
        int i = 0, j = 0, bombs = 0, numero_bombas = 10, x;
        int map[size][size];
    
        // Creamos las bombas y contamos las bombas al mismo tiempo
        while (bombs != 10) {
          bombs = 0;
    
          for (i = 0; i < size;i++)
              for (j = 0; j<size; j++)
                map[i][j] = 0;
    
          for (i = 0; i < size;i++)
              for (j = 0; j<size; j++) {
                x = rand() % 100 + 1;
    
                if (x <= numero_bombas) {
                  map[i][j] = 1;
                  bombs++;
                }
              }
        }
    
        // Imprimimos la matriz y la cantidad de bombas que tiene
        printf("bombs = %d\n", bombs);
        for(i = 0; i < size; i++) {
            for(j = 0; j < size; j++)
                printf("%d ", map[i][j]);
            puts("");
        }
    
        getchar();
    
        return 0;
    }
    

    Note that in the code add the variable numero_bombas that would represent the number of bombs you want to put on the board.

    The method I use to put a number of bombs on the board is to randomly place bombs in each cell according to a certain probability, if the board has a different number of bombs than what is wanted, then it becomes to try to put bombs randomly until the number of bombs is the one that is desired.

    Greetings.

        
    answered by 16.09.2017 в 07:44