HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Ant Colony Simulator

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simulatorcolonyant

Problem

This program is a simulation of an ant colony, inspired by SimAnt. It doesn't do it off the batch; there must be code that instructs the ants to follow scent tiles in particular and react to the food.

main.cpp

It's the main file that must be modified to put more/less ants, more/less food/ants (generators or not).

#include "tile.cpp"
#include "foodFactory.cpp"
#include "scent.cpp"
#include "tile.cpp"
#include 
#include 

using namespace std;

int main() {
    foodFactory a(43, 12);
    a.splatFood();
    antFactory b(12, 95);
    b.makeAnt();
    b.makeAnt();
    b.makeAnt();
    bool exit = false;
    while(exit == false)
    {
        b.tickAnts();
        sleep(500).
        if (cin.good())
        {
            exit = true;
        }
    }
    return 0;
}


antFactory.cpp

Despite the filename, this contains the ant code and the ant factory code. The ant's class code must be modified so they grab food and wander to find food and move to the food and follow scent and the general AI & behaviour.

```
#pragma once
#include "scent.cpp"
#include
#include

using namespace std;

class ant
{
private:
int x;
int y;
int index;
antScent newDropScent;
bool foundFood;
public:
ant(int nx, int ny, int i)
{
x = nx;
y = ny;
index = i;
}
pair moveThisAnt(pair dir, pair move)
{
if (move.first)
{
if (dir.first)
x += 1;
else
x -= 1;
}
if (move.second)
{
if (dir.second)
y += 1;
else
y -= 1;
}
pair result;
result.first = x;
result.second = y;
return result;
}
void tickThisAnt() {
cout antGenerated;
public:
ant* makeAnt()
{
ant z(x, y, antGenerated.size() + 1);
antGenerated.push_back(z);
return &antGenerated[antGenerated.size() - 1];
}
antFactory(int nx, int ny) {

Solution

Generating better random numbers

Don't use rand(). It's a horrible, deprecated function that doesn't actually generate numbers that seem to be truly random. At a quick glance it seems like it, but don't be fooled - it's not.

If you want to generate true-ish random numbers, you're going to need to include the following header to start off:

#include 


Next, you want to create a random engine. Since we don't want to re-create our random engine every time we want to generate a number, we're going to create the following helper function to create an engine for us:

// credit: http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/
std::mt19937& random_engine()
{
    thread_local static std::random_device random_device { };
    thread_local static std::mt19937       engine { random_device() };
    return engine;
}


Next, in order to use, it, all you have to do is this:

thread_local static std::uniform_int_distribution<> distribution { a, b };
int result = distribution(random_engine())


Just replace a and b with the low and high numbers in your range.

The above examples should work, but I didn't have time to test them, so please notify me if it doesn't work.

Class definition and declaration

Traditionally, if your class is long enough, instead of declaring a class and defining its methods, you'd declare it something like this:

class MyClass
{
public:
    type foo;
    type bar;

    MyClass(type foo, type bar)
        : foo(foo)
        , bar(bar)
    {}

    void doSomething();
    void doOtherthing();
};


And then implement the methods somewhere else, usually in a different file:

MyClass::doSomething()
{
    ...
}

MyClass::doOtherthing()
{
    ...
}


In addition, you should initialize class properties inside the constructor using an initialization list, like this:

Constructor(type a, type b, type c)
    : a(a)
    , b(b)
    , c(c)
{}


It's also worth noting that the arguments to your constructor don't need to be named differently than the class properties that they represent.

using a namespace named std

Never write this line of code:

using namespace std;


This is a mistake that beginners often make due to a bad online tutorial, or a beginners C++ book using it. There are many bad things that can go quite wrong here. The bad things that can happen are best described on this Stack Overflow question, but I'll outline a few here:

  • Name conflicts between std and another namespace.



  • Function conflicts between std and another namespace.



  • Function conflicts between std and another namespace with the same arguments. (This is especially bad.)



In the end, having to prefix some names with std:: is much better than the adverse side effects that come about due to using namespace std;.

Stuff related to styling/Nitpicks

You're inconsistent on how you're styling your classes. Sometimes you write them like this:

class Foo {
public:
    ...

private:
    ...
}


Other times you're writing them like this:

class Foo {
    public:
        ...

    private:
        ...
}


The overall idea I'm trying to convey is to be consistent. When you, and others are reading or working on your code, it's important that it's as clear as possible. Code that is written using inconsistent styles and techniques is always bad on some level, in some way.

While there is no true official standard for naming classes in C++, most people usually name their classes in the naming style PascalCase, not camelCase.

The following line of code at the end of main is redundant:

return 0;


Most, if not all, modern C++ compilers will automatically insert return 0; into main.

Finally, if you want a reliable std::string in your code, you should be including the following header whenever you're using strings:

#include 

Code Snippets

#include <random>
// credit: http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/
std::mt19937& random_engine()
{
    thread_local static std::random_device random_device { };
    thread_local static std::mt19937       engine { random_device() };
    return engine;
}
thread_local static std::uniform_int_distribution<> distribution { a, b };
int result = distribution(random_engine())
class MyClass
{
public:
    type foo;
    type bar;

    MyClass(type foo, type bar)
        : foo(foo)
        , bar(bar)
    {}

    void doSomething();
    void doOtherthing();
};
MyClass::doSomething()
{
    ...
}

MyClass::doOtherthing()
{
    ...
}

Context

StackExchange Code Review Q#116171, answer score: 8

Revisions (0)

No revisions yet.