Game of Life Modification 2D Grid Movement

Hey Cplusplus community.

I am a long time reader of these forum threads but this is my first actual post so please tell me if there is anything I should do differently in future.

I am posting about a problem I am having with one of my OOP c++ assignments.

I am trying to recreate an ASCII simulation of a modified version of Conways game of life.

In this version there are 3 main organisms, Bacteria, Creepers, and Creeperphages

In a nutshell I have generated a 2D grid of which I will also generate a number of the different organisms mentioned above. It is a typical predator vs prey setup where each organism has different traits.

Bacteria do not move
Creepers move in 4 directions, and eat Bacteria to stay alive


I have programmed quite a lot of the initial setup, however I am not sure how efficient it is and I would like to learn the most efficient techniques for using pointers, inheritance, structs, etc.

My main two problems come with the movement and the maps dimensions to make it dynamic.

First the movement, I am not sure how I can make it so that I can always check whether a maps x,y coordinates are occupied by a creature.

Second, I still have no easy way for my classes to be able to access the maps dimensions. So at the moment my simulation is set to a static dimension however I would like the user to be able to input the dimensions at the start and then for the Creeper class movement function to check whether it is still within the grid.

I have tried making the map into a singleton (Read up about that today) to no avail

Here is my code so far, really any help at all would be extremely valuable.


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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//Main.cpp
  #include <iostream>
using std::cout;
using std::endl;

#include <vector>
using std::vector;

#include <typeinfo>
#include "time.h"
#include "Organism.h"
#include "WorldMap.h"
#include "Bacteria.h"
#include "Creeper.h"
int MapWidth = 10;
using namespace std;
WorldMap map;
int main()
{
    int noBacteria;
    int noCreeper;
    srand(time(0));

    map.setWidth(5);
    map.setHeight(6);



    //map.Initialise();
    map.initialiseMap();
    //map.PrintMap();
    //cout << "Maps dimensions are width:  "<< map.getWidth()<<" & height: "<<map.getHeight()<<"\n";
    cout << "How many Bacteria will there be?\n";
    cin >> noBacteria;
    //Would normally get the number of Bacteria here
    vector < Organism * > bacteria( noBacteria );


    for (int i=0;i<noBacteria;i++){
        bacteria[i] = new Bacteria(0,0,'B');
        map.setCoord(bacteria[i]->getCoordX(),bacteria[i]->getCoordY(),bacteria[i]->getIcon());
    }

    cout << "How many Creeper will there be?\n";
    cin >> noCreeper;
     vector < Organism * > creeper( noCreeper );

     for (int i=0;i<noCreeper;i++){
         creeper[i] = new Creeper(0,0,'C',10);
         map.setCoord(creeper[i]->getCoordX(),creeper[i]->getCoordY(),creeper[i]->getIcon());
     }


    //vector< Organism * > organism()
    map.PrintMap();

}


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
//WorldMap.h

#ifndef WORLDMAP_H
#define WORLDMAP_H

// Include the relevant libraries
#include<iostream>
#include<cstdlib>
#include<cstdio>

#include "Organism.h"
using namespace std;//Use std namespace

class WorldMap
{
public:
    WorldMap();
    void setWidth(int);
    void setHeight(int);
    int getWidth();
    int getHeight();
    void PrintMap();
    void setCoord(int,int,char);
    void setIcon(char);
    char getIcon(int,int);
    void initialiseMap();
    char Map[100][100];



private:
    int _width;
    int _height;
    char _icon;
    int _CoordX;
    int _CoordY;

};

#endif // WORLDMAP_H 



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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//WorldMap.cpp

#include "WorldMap.h"

WorldMap::WorldMap()
{

    /*if (width<=0)
    {
        cout << "width cannot be negative, default width of 10 has been set";
        setWidth(10);
    }
    else
    {
        setWidth(width);
    }
    if (height<=0)
    {
        cout << "height cannot be negative, default height of 10 has been set";
        setHeight(10);
    }
    else
    {
        setHeight(height);
    }
    //Map.resize[width][height];*/
}



void WorldMap::setWidth(int width)
{
    _width = width;
}

int WorldMap::getWidth(){
    return _width;
}


void WorldMap::setHeight(int height)
{
    _height = height;
}

int WorldMap::getHeight(){
    return _height;
}

void WorldMap::PrintMap(){
    for (int i=0;i<=_height-1;i++)
    {
        for(int j=0;j<=_width-1;j++)
        {
            cout << Map[i][j];
        }
        cout << "\n";
    }
}


void WorldMap::setCoord(int CoordX,int CoordY, char icon)
{
    _CoordX=CoordX;
    _CoordY=CoordY;
    _icon = icon;
    Map[_CoordX][_CoordY] = icon;
}

void WorldMap::setIcon(char icon)
{
    _icon = icon;
}

char WorldMap::getIcon(int CoordX,int CoordY)
{
    return _icon;
}

void WorldMap::initialiseMap(){
    for (int i=0;i<=_height-1;i++)
    {
        for(int j=0;j<=_width-1;j++)
        {
            Map[i][j] ='0';
        }
    }
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Bacteria.h
#ifndef BACTERIA_H
#define BACTERIA_H

#include "Organism.h"
#include "WorldMap.h"
class Bacteria : public Organism{

public:
    Bacteria(int,int,char);


protected:



};

#endif // BACTERIA_H 


1
2
3
4
5
6
7
8
9
10
#include "Bacteria.h"
#include "WorldMap.h"
#include "Organism.h"

Bacteria::Bacteria(int CoordX,int CoordY, char icon):Organism(CoordX, CoordY,icon)
{
    icon = 'B';
    //char getIcon();

}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#ifndef CREEPER_H
#define CREEPER_H

#include "Organism.h"
#include "WorldMap.h"

class Creeper :public Organism{
public:
    Creeper(int,int,char,int);
    void getMovement(int, int);
protected:
    int weight;
    int CoordXnew;
    int CoordYnew;
    int CoordX;
    int CoordY;
};

#endif // CREEPER_H


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Creeper.cpp
#include "Creeper.h"
#include "WorldMap.h"
#include "Organism.h"

Creeper::Creeper(int CoordX,int CoordY, char icon, int weight):Organism(CoordX, CoordY,icon)
{
    icon = 'C';
    //cout << getCoordX();
}

void Creeper:: getMovement(int CoordX, int CoordY){

}


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

#ifndef ORGANISM_H
#define ORGANISM_H

#include "WorldMap.h"

class Organism
{
public:
    Organism(int CoordX,int CoordY,char icon);

    void setCoordXY(void);
    int getCoordX();
    int getCoordY();
    void setIcon(char);
    char getIcon(void);
protected:
    int _CoordX;
    int _CoordY;
    char _icon;

};

#endif // ORGANISM_H

//Organism.cpp
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

#include "Organism.h"
#include "time.h"
#include "WorldMap.h"
Organism::Organism(int CoordX,int CoordY,char icon)
{
    setCoordXY();
    setIcon(icon);
}



void Organism::setCoordXY()
{
    _CoordX = rand()%6;
    _CoordY = rand()%5;
}

int Organism::getCoordX()
{
    return _CoordX;
}

int Organism::getCoordY()
{
    return _CoordY;
}

void Organism::setIcon(char icon){
    _icon = icon;
}

char Organism:: getIcon()
{
    return _icon;
}
Dynamic size require dynamic memory allocation, meaning you will have to use keyword new and work on pointers rather that static arrays - look at examples below.
As for the second question: your organism class is not aware of the WorldMap it exists in. To allow organisms check the state of the WorldMap, the Organism class needs WorldMap pointer. I can think of several ways of doing this, but I would recomend adding static variable to class Organism, so that each organism has reference to the map:

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
// WorldMap.h
class Organism;

class WorldMap
{
public:
	WorldMap(int x = 100, int y = 100);

	int getWidth();
	int getHeight();
	Organism * getOrganismAt( int x, int y);
	void PutOrganismIn(int x, int y, Organism * organism);


private:
	int _width;
	int _height;
	
	// This is a pointer to pointer to Organism. I will use it as 
	// 1-D array of pointers to Organism, and not 2D array.
	// I used pointers to Organisms rather that char, because
	// it gives you the way of calling this WorldMap inhabinants 
	// member functions directly form the WorldMap class.
	// Is it clear, or am I hard to follow?
	Oragnism** _organisms; // flattened, not to add pointer confusion
				// getOrganismAt() will handle doind 2d calculations

};

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
#include "WorldMap.h"
#include "Organism.h"

WorldMap::WorldMap(int width, int height)
{
	_width = width;
	_height = height;

	// I change pointer to pointer into a new array of pointers of 
	// size of my choice
	_organisms = new Organism* [_width * _height];
	
	for (int i = 0; i < (_width * _height); i++)
	{
		_organisms[i] = 0; // no organism there yet so points to 0.
	}
}

int WorldMap::getWidth()
{
	return _width;	
}
int WorldMap::getHeight()
{
	return _height;
}

// 2-D coordinates to look in 1-D array
Organism* WorldMap::getOrganismAt( int x, int y)
{
	return _organisms [ _width * x + y ];
}

void WorldMap::PutOrganismIn(int x, int y, Organism * organism)
{
	_organisms [ _width * x + y] = organism;
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Organism.h

class WorldMap; // declaration of the other class
class Organism
{
public:
	static void setWorldMap (WorldMap * map);

	Organism(int x, int y, char type);
	char getType();
	int getX();
	int getY();
	void setPosition (int x, int y);
	bool hasLivingNeighbour();
protected:
	int _X;
	int _Y;
	char _type;
	static WorldMap* _world;

};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Organism.cpp
bool Organism::hasLivingNeighbour();
{
	Organism * left = 0;
	Organism * top = 0;
	Organism * right = 0;
	Organism * bottom = 0;
	if( getX() > 0 )
		left = _world->getOrganismAt ( getX() - 1, getY() );
	if( getX() < _world -> getWidth() - 1 )
		right = _world -> getOrganismAt ( getX() + 1, getY() );
	if( getY() > 0 )
		top = _world -> getOrganismAt ( getX(), getY() - 1 );
	if( getY() < _world -> getHeight() - 1 )
		bottom  = _world -> getOrganismAt ( getX(), getY() + 1 );
	if (left || right || top || bottom )
		return true;
	else 
		return false;
}

1
2
3
4
5
6
7
8
9
10
11
//main.cpp

#include "WorldMap.h"
#include "Organism.h"

int main()
{
	World map = new map (1024, 1024);
	Organism::setWorldMap(map); 
	// ... 
}
Last edited on
Hey JockX from the looks of it this code will be really useful to help me understand pointers and dynamic memory allocation (never have understood this). I will look over it for the next couple of hours then get back to you. Thanks so much for the quick reply and help.
Topic archived. No new replies allowed.