patterncppMinor
Quite-Off-The-Bat Complex Console Ant Colony Simulator w/ Partial AI
Viewed 0 times
thequiteantcolonypartialsimulatorconsoleoffcomplexbat
Problem
As a follow-up of my previous non-off-the-bat Ant Colony Simulator, we have this one that works off-the-bat... quite; the code for when the ants find and take the food isn't really done but it would be almost impossible to do it anyway, if someone wants to contribute directly to the code, please do it in GitHub.
scent.cpp
antFactory.cpp
```
#pragma once
#include "scent.cpp"
#include "randbool.h"
#include
#include
#include
#include "foodFactory.cpp"
#include "board.cpp"
#include "tile.h"
#define DEBUG
#ifndef ANTFACTORY_CPP_INCLUDED
#define ANTFACTORY_CPP_INCLUDED
class Ant
{
private:
int x;
int y;
Board* pertainingBoard;
tile* Position;
int index;
AntScent NewDropScent;
bool bFoundFood = false;
short AntSize;
bool bIsCarryingFood;
std::pair newPos;
std::pair FoodPos;
public:
Ant(int nx, int ny, int i, Board* pb)
{
x = nx;
y = ny;
index = i;
pertainingBoard = pb;
pertainingBoard->addAnt(this);
}
std::pair moveThisAnt(std::pair dir, std::pair move)
{
if (move.first)
{
if (dir.first)
x += 1;
else
x -= 1;
}
if (move.second)
{
if (dir.second)
y += 1;
else
y -= 1;
}
#ifdef DEBUG
std::cout result;
result.first = x;
result.second = y;
return result;
}
scent.cpp
#ifndef SCENT_CPP_INCLUDED
#define SCENT_CPP_INCLUDED
class AntScent
{
private:
short power;
short angle;
short ScentType;
public:
short addPower()
{
power += 1;
return power;
}
short affectAngle(short vel)
{
angle = (vel + angle) / 2;
return angle;
}
void ChangeType(short NewType)
{
ScentType = NewType;
}
short decreasePower()
{
power -= 1;
return power;
}
};
#endif // SCENT_CPP_INCLUDEDantFactory.cpp
```
#pragma once
#include "scent.cpp"
#include "randbool.h"
#include
#include
#include
#include "foodFactory.cpp"
#include "board.cpp"
#include "tile.h"
#define DEBUG
#ifndef ANTFACTORY_CPP_INCLUDED
#define ANTFACTORY_CPP_INCLUDED
class Ant
{
private:
int x;
int y;
Board* pertainingBoard;
tile* Position;
int index;
AntScent NewDropScent;
bool bFoundFood = false;
short AntSize;
bool bIsCarryingFood;
std::pair newPos;
std::pair FoodPos;
public:
Ant(int nx, int ny, int i, Board* pb)
{
x = nx;
y = ny;
index = i;
pertainingBoard = pb;
pertainingBoard->addAnt(this);
}
std::pair moveThisAnt(std::pair dir, std::pair move)
{
if (move.first)
{
if (dir.first)
x += 1;
else
x -= 1;
}
if (move.second)
{
if (dir.second)
y += 1;
else
y -= 1;
}
#ifdef DEBUG
std::cout result;
result.first = x;
result.second = y;
return result;
}
Solution
I see a number of things that could help you improve your program.
Don't use
No doubt others will disagree on this one, but they can write their own reviews. In my projects, I use
Don't use
The use of
Don't
Similar to the first two points, you shouldn't
scent.h
scent.cpp
Rethink your classes
There are a lot of classes here, which isn't necessarily a bad sign, but they all seem to rely on each other. In other words, the level of coupling is very high, which is a sign of trouble. For example, the
Simplify your code
If we look at the
However this could be both more idiomatic C++ and also shorter:
Use a better random number generator
Modern C++ has much better random number generators than
There's more, but it's all I have time for at the moment.
Don't use
#pragma onceNo doubt others will disagree on this one, but they can write their own reviews. In my projects, I use
#include guards instead. The advantage is that it's specified in the standard, while any #pragma is, by definition, non-standard. Some claim that it's faster to compile when using #pragma once but I'd recommend that you actually measure it both ways and see for yourself.Don't use
#pragma once in a .cpp fileThe use of
#pragma once (or an #include guard) is for headers that might be included in multiple source files. Neither should be used in .cpp files.Don't
#include a .cpp fileSimilar to the first two points, you shouldn't
#include a .cpp file within a header file. It is sometimes OK to #include a .cpp file within another .cpp file as for certain kinds of autogenerated source code but this project does not have such special cases and shouldn't #include any .cpp files within either .h or .cpp files. To show how this should be done, here are scent.cpp and scent.h files rewritten to follow these conventions:scent.h
#ifndef SCENT_H
#define SCENT_H
class AntScent
{
private:
short power;
short angle;
short ScentType;
public:
short addPower();
short affectAngle(short vel);
void ChangeType(short NewType);
short decreasePower();
};
#endif // SCENT_Hscent.cpp
#include "scent.h"
short AntScent::addPower()
{
power += 1;
return power;
}
short AntScent::affectAngle(short vel)
{
angle = (vel + angle) / 2;
return angle;
}
void AntScent::ChangeType(short NewType)
{
ScentType = NewType;
}
short AntScent::decreasePower()
{
power -= 1;
return power;
}Rethink your classes
There are a lot of classes here, which isn't necessarily a bad sign, but they all seem to rely on each other. In other words, the level of coupling is very high, which is a sign of trouble. For example, the
Ant class has pointers to both the Board it is on and the tile it is on as well as its own x and y coordinates and also its own index within a vector which is a private member of the AntFactory class! That is just way too much information for a little Ant to track! If we think about actual ants, individual ants probably don't actually have much concept of these things. Instead, the Board should contain the collection of ants that is currently in the AntFactory class. Next, the AntFactory shoul only generate a new Ant and nothing else. The Board should also keep each Ant's position rather than the Ant itself. Similarly, a Board should include a collection of tile objects. The Board should keep track of the positions of each tile and not each tile.Simplify your code
If we look at the
AntScent::addPower() routine, it is currently this:short AntScent::addPower()
{
power += 1;
return power;
}However this could be both more idiomatic C++ and also shorter:
short AntScent::addPower()
{
return ++power;
}Use a better random number generator
Modern C++ has much better random number generators than
rand(). A random variable that only has true or false values is called a Bernoulli distribution and it's already built into C++11's `` header. Use this:#include
bool MyRandomBoolean() {
static std::random_device rd;
static std::mt19937 gen(rd());
static std::bernoulli_distribution d; // default is 50:50 distribution
return d(gen);
}There's more, but it's all I have time for at the moment.
Code Snippets
#ifndef SCENT_H
#define SCENT_H
class AntScent
{
private:
short power;
short angle;
short ScentType;
public:
short addPower();
short affectAngle(short vel);
void ChangeType(short NewType);
short decreasePower();
};
#endif // SCENT_H#include "scent.h"
short AntScent::addPower()
{
power += 1;
return power;
}
short AntScent::affectAngle(short vel)
{
angle = (vel + angle) / 2;
return angle;
}
void AntScent::ChangeType(short NewType)
{
ScentType = NewType;
}
short AntScent::decreasePower()
{
power -= 1;
return power;
}short AntScent::addPower()
{
power += 1;
return power;
}short AntScent::addPower()
{
return ++power;
}#include <random>
bool MyRandomBoolean() {
static std::random_device rd;
static std::mt19937 gen(rd());
static std::bernoulli_distribution d; // default is 50:50 distribution
return d(gen);
}Context
StackExchange Code Review Q#116258, answer score: 6
Revisions (0)
No revisions yet.