Question:
How would I make a 2d vector and populate it with randomly placed chars C++?
Ben Chambers
2013-01-20 16:22:19 UTC
I have been spending the last few weeks making a simple mine sweeper game. I now have a working game but a few days left to improve it. I have used static arrays for different 'levels' which make the code 4 or 5 times bigger than it needs to be. Now I understand the how the whole program works I would like to try and use vectors or dynamic arrays in place of static arrays.

Here is my solution to creating the arrays and populating them with random mines (M):

srand(time(NULL));
char displayarray[5][5] = {{'?','?','?','?','?',}, //Declaring grid arrays
{'?','?','?','?','?',},
{'?','?','?','?','?',}, //User will see this array
{'?','?','?','?','?',},
{'?','?','?','?','?',}};
char minearray[5][5] = {{'0','0','0','0','0',},
{'0','0','0','0','0',},
{'0','0','0','0','0',}, //Hidden array for mines
{'0','0','0','0','0',},
{'0','0','0','0','0',}};
int guessedarray[5][5]; //Empty array to store guesses

for(int x=0; x {
row = rand ()%5; //Rand statement to generate random numbers
column = rand()%5;
if (minearray[row][column] !='M') //Checking if array location contains a mine (M)
{
minearray[row][column] = 'M'; //If no mine, mine will be placed using random location
}
else x--; //If mine exists, counter decreases so loop can try again
} //Array now populated

or http://pastie.org/5744198

How would I replicate this with vectors or dynamic arrays. And then how do I read user defined locations to check if M exists in that location.

Thanks.
Three answers:
cja
2013-01-21 07:01:52 UTC
Using vectors might be nice, but simple 2D arrays of char aren't bad for this application. You can update your code like this:



#include

#include

#include

#include

#include

#include

#include

#include



using namespace std;



void getInt2(const string&, char, int *, int *);

template

T **new2dArray(int, int, T);

template

void showArray(T **, int, int);

const char comma(',');



int main(int argc, char *argv[]) {

  int rows, cols, noofmines;

  char **displayarray, **minearray;

  int **guessedarray, row, col;



  srand(time(NULL));

  do {

    getInt2("Enter rows, cols: ", comma, &rows, &cols);

  } while ((rows < 1) || (cols < 1));

  displayarray = new2dArray(rows, cols, '?');

  minearray = new2dArray(rows, cols, '0');

  guessedarray = new2dArray(rows, cols, 0);

  noofmines = rand() % (rows * cols / 2);



  for (int x = 0; x < noofmines; x++) {

    while (minearray[row = rand() % rows][col = rand() % cols] == 'M');

    minearray[row][col] = 'M';

  }

  showArray(displayarray, rows, cols);

  showArray(minearray, rows, cols);

  showArray(guessedarray, rows, cols);

  return 0;

}



template

T **new2dArray(int rows, int cols, T init) {

  T **a = new T *[rows];



  for (int i = 0; i < rows; i++) {

    a[i] = new T[cols];

    for (int j = 0; j < cols; a[i][j++] = init);

  }

  return a;

}



template

void showArray(T **a, int rows, int cols) {

  for (int i = 0; i < rows; i++) {

    copy(a[i], a[i] + cols, ostream_iterator(cout, " "));

    cout << endl;

  }

  cout << endl;

}





void getInt2(const string &s, char delim, int *a, int *b) {

    string in;

    stringstream ss;

    char c;

    bool inputOk;

   

    cout << s;

    do {

        getline(cin,in);

        ss.clear(); ss.str(in);

        inputOk = (ss >> *a >> c >> *b) && (c == delim) && !ss.good();

        if (!inputOk) {

            cout << "Invalid input, try again." << "> ";

        }

    } while (!inputOk);

}



#if 0



Sample run:



Enter rows, cols: 7, 5

? ? ? ? ?

? ? ? ? ?

? ? ? ? ?

? ? ? ? ?

? ? ? ? ?

? ? ? ? ?

? ? ? ? ?



0 M 0 0 0

M M 0 0 M

0 0 M M 0

0 0 0 0 M

0 0 M M 0

M M 0 0 M

0 0 0 M 0



0 0 0 0 0

0 0 0 0 0

0 0 0 0 0

0 0 0 0 0

0 0 0 0 0

0 0 0 0 0

0 0 0 0 0



#endif
2013-01-21 01:18:02 UTC
You don't need to use arrays. It is fine to use more advanced c++ objects like vectors but you should really learn how to use dynamic allocation using pointers.



Secondly I really doubt you are increasing the size of your program that much unless you are declaring thousands of different minefield sizes and besides is the disk size on your computer small enough to matter?



Before moving on to vectors you really should learn how to use pointers.



#define MF_SIZE 5

char **minefield;



minefield = new char*[MF_SIZE];

for(int in = 0; in < MF_SIZE; in++)

{

minefield[in] = new char[MF_SIZE];

}



now you can access minefiled the same way you can if it was an array



you can use MF_SIZE as a default value and still input the size of the minefield from the user.

Instead of using MF_SIZE, you can replace it with an integer and input the size from the user and create the dynamic "array" in the same fashion as above. Of course, good programming practive is to delete the elements if you are changing the size of minefield throughout the course of running the application.
?
2013-01-21 01:17:50 UTC
Well with a vector your character arrays can look like this instead:



    std::vector> displayarray(5, std::vector(5, '?'));

    std::vector> minearray(5, std::vector(5, '0'));

    std::vector> guessedarray(5);



If you want a user-inputted length you can set variables and replace "5" in the above code with variables after having gotten the value from them. -- http://stacked-crooked.com/view?id=e38b6512bd63bda7d6ad1785d6d9ab64


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...