gcccpp
gcccpp

Reputation: 59

How do I initialize a 2D array of variable size in a C++ class?

I am working on a tic tac toe program and I need to create a 2D array of variable size in a class. This is how I have it written now:

class ticTacToe
{
     public:
         ticTacToe();
         void display();
         bool moveIsValid();
     private:
         int rows;
         int cols;
         int board[rows][col];
}

I have the board being read in from a file in the constructor but I am not sure how to make it of variable size so that I can read in a board of any size and then access it outside of the class.

Upvotes: 4

Views: 4848

Answers (4)

Iresh Rajitha Kalhara
Iresh Rajitha Kalhara

Reputation: 11

I suggest you to use pointer to pointer.

#include <iostream>
#include <cstdlib>

using namespace std;

class ticTacToe{
private:
    int rows;
    int cols;
    int **board; // POINTER TO POINTER
public:
    ticTacToe(int a,int b){
        rows=a;
        cols=b;
        board=new int*[rows];

        for (int k = 0; k < rows; ++k) {
            board[k]=new int[cols];
        }

        /*LET'S INITIALIZE CELL VALUES TO= 0*/
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                board[i][j]=0;
            }
        }
    }
    void display();
    bool moveIsValid();
};

Upvotes: 0

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

"I have the board being read in from a file in the constructor but I am not sure how to make it of variable size so that I can read in a board of any size"

In c++ you use a std::vector instead a raw array like follows

class ticTacToe {
     public:
         ticTacToe();
         void display();
         bool moveIsValid();
     private:
         int rows;
         int cols;
         std::vector<std::vector<int>> board; // <<<<
};

The dynamic allocation can be applied as follows in a constructor:

ticTacToe(int rows_, int cols_) : rows(rows_), cols(cols_) {
    board.resize(rows,std::vector<int>(cols));
}

and then access it outside of the class

Well, I'm not sure that this is really a good idea, but you can simply add an accessor function for that member variable

 std::vector<std::vector<int>>& accBoard() { return board; }

The better design approach would be IMHO, to provide something like a separate function to read from a std::istream:

 void ticTacToe::readFromStream(std::istream& is) {
     // supposed the first two numbers in the file contain rows and cols
     is >> rows >> cols;
     board.resize(rows,std::vector<int>(cols));
     for(int r = 0; r < rows; ++r) {
         for(int c = 0; c < cols; ++c) {
             cin >> board[r][c];
         }
     }
 }

For real code you would check for input errors of course like

 if(!(is >> rows >> cols)) {
    // handle errors from input
 }

Upvotes: 5

ichramm
ichramm

Reputation: 6642

In case this is homework and you cannot use the standard library:

// Declaration
int rows;
int columns;
int **board;

// Construction

board = new int*[rows];
for (int i = 0; i < rows; i++) {
    board[i] = new int[columns];
}

// Destruction


for (int i = 0; i < rows; i++) {
    delete[] board[i];
}
delete[] board;

Update: You could perform a single allocation but it will be easier for you to work it this way.

Upvotes: 4

Cory Kramer
Cory Kramer

Reputation: 117876

You either need to have a dynamically sized array

int* board;

Then your constructor would be

ticTacToe::ticTacToe(int _rows, int _cols)
: rows{_rows}, cols{_cols}
{
    board = new int[rows * cols];
}

And your destructor

ticTacToe::~ticTacToe()
{
    delete[] board;
}

Or better yet use a std::vector

std::vector<int> board;

Then your constructor would be

ticTacToe::ticTacToe(int _rows, int _cols)
: rows{_rows}, cols{_cols}
{
    board.resize(_rows * _cols);
}

Upvotes: 1

Related Questions