function returning a pointer to a 2d array

Hi,

I am relatively new to programming, having read up on it in order to learn the basics. I am working on my first game, a tetris clone, and I need a function that returns a pointer to a 2d array of booleans, but pointers are confusing me slightly.

Below is the tetromino class, thats what the pieces are called in tetris in case anyone didnt know...

#pragma once
#include "HAPI_lib.h" Hapi is the name of the API I'm using
typedef unsigned char BYTE;

class CTetromino
{
public:
CTetromino(void);
CTetromino(int i);
~CTetromino(void);
void Initialise(int i);
void Rotate();
bool & getGrid();
void draw(int posX, int posY);
private:
int texRef; //reference to the array of textures in CVisualisation
bool grid[4][4]; This is what I want to return a pointer to in the function below

};

bool & CTetromino::getGrid()
{
bool * ptr = new bool[4][4]; error C2440: 'initializing' : cannot convert from 'bool (*)[4]' to 'bool *'
ptr = &grid; error C2440: '=' : cannot convert from 'bool (*)[4][4]' to 'bool *'
return * ptr;
}

I am very confused...It's clear that I don't properly understand how pointers work and I would greatly appreciate some help =)

thanks.
Michael.

1
2
3
4
bool* CTetromino::getGrid()
{
return (bool*)grid;
}


The simplest solution.

BTW: I dont think you can declare the variables after the functions. Move them before public: just to be safe...
Last edited on
Hi!

How can I return a 2 dimension array?

For example:

1
2
3
4
bool [][4] CTetromino::getGrid()
{
 return grid;
}


Because I can't do it.
you cant return arrays of any sort. Just use the pointer as you would an array.

1
2
3
4
5
6
7
8
9
10
bool* CTetromino::getGrid()
{
return (bool*)grid;
}

//...
bool* ret;
ret=tetro.getGrid();
ret[0][1]=true;
//... 
Thanks gregor my getGrid() function works now =) but I've encountered another problem.

The function below will be called when the tetromino has reached its lowest possible point and needs to be locked into position, this is done by copying the layout of the grid from the tetromino and changing the 10x18 grid in 'CWorld' which contains every block in the level that has been locked down, this grid is initialised to zero when the program runs, which when the level is drawn, draws the default background colour.

void CWorld::Lockdown()
{
bool* tet = tetrominoes[current.ref].getGrid(); // Works okay, tet now contains the layout of the current tetromino
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
if (tet[i][j] == true) // error C2109: subscript requires array or pointer type
worldArray[i][j] = current.ref; // worldArray is my 10x18 grid
}
}
}

Don't worry about current.ref its just an integer used to reference textures and represent which colour the block at that position is. the error seems to think that 'tet' is not a valid pointer though I think, but it points to an array and I've gone through my code using breakpoints to check that it is valid, it gets the value from getGrid() just fine. Any ideas?
jh never tried that anyhow.

Notes on problem:
Yeh, since operator [] dereferences the pointer, you cant use another [] op on it.

Again, there is no way to return multidimensional arrays, and if compiler doesnt know about the size of dimensions he cant calculate the right position, and he will use op [] as on normal, single dimensional arrays.

That means that you will have to calculate the position of an element runtime, yourself.

Solutions:
(pointer+(width*x))[y]

pointer[width*y+x]
Last edited on
Ah right, I'm starting to think that I may have jumped into the deep end slightly too early as I have no idea what dereference means =p, but I'll give it a shot. Out of curiosity would I suffer the same problem if I changed the array named grid, in CTetromino, to a 2d vector?
No, but you will have to return a pointer to it, as you do now.


Vector solution:
1
2
3
4
5
6
7
8
using std::vector;
vector<vector<bool>> testvec;
vector<bool> tmp;
tmp.assign(4, true);
testvec.assign(4, tmp);

testvec[0][0]=false;
testvec[2][0]=false;



Also, I've coded this template class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdarg.h>
template <class Ty>
class Field{
	Ty* Mem;
	unsigned char* dims;
	unsigned char d;
public:
	Ty& operator() (unsigned char first, ...){
		va_list va;
		va_start(va, first);
		Ty* ret = Mem+(dims[0]*first);
		if(d>1)
			for(unsigned char i = 1; i<d; i++){
				unsigned char tmp = va_arg(va, unsigned char);
				ret+=(dims[i]*tmp);
			};
		va_end(va);
		return (*ret);
	};
	Field(char dimensions, ...){
		va_list va;
		va_start(va, dimensions);
		d=dimensions;		
		dims=new unsigned char[dimensions];
		unsigned char* tmp = new unsigned char[dimensions];
		dims[0]=1;
		for(unsigned char i=0; i<dimensions; dims[0]+=tmp[i++]=va_arg(va,unsigned char));
		for(unsigned char j=0; j<dimensions; j++){
			dims[j]=1;
			for(unsigned char i=j+1; i<dimensions; dims[j]*=tmp[i++]);
		}
		Mem = new Ty[dims[0]+tmp[0]];
		delete [] tmp;
		alloc = true;
		va_end(va);
	}

	~Field(){
		delete [] dims;
		delete [] Mem;
	};
};


Usage:

1
2
Field<bool> grid(2 /*Number of dimensions*/, 4, 4);
grid(0,2) = true;//Sets [0][2] to true 


I think its better than using vectors in your case.
Last edited on
^^post

You can return this grid and it will just copy itself, like so:
1
2
3
4
5
Field<bool> CTetromino::getGrid()
{
return grid;//Given that grid is a Field
}


Or, if you want to allow the user to change your data

1
2
3
4
Field<bool>& CTetromino::getGrid()
{
return grid;//Given that grid is a Field
}
Great! Thanks Gregor, problem solved.
Topic archived. No new replies allowed.