patterncppMinor
Ant Colony Simulator
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).
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) {
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
If you want to generate true-ish random numbers, you're going to need to include the following header to start off:
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:
Next, in order to use, it, all you have to do is this:
Just replace
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:
And then implement the methods somewhere else, usually in a different file:
In addition, you should initialize class properties inside the constructor using an initialization list, like this:
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.
Never write this line of code:
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:
In the end, having to prefix some names with
Stuff related to styling/Nitpicks
You're inconsistent on how you're styling your classes. Sometimes you write them like this:
Other times you're writing them like this:
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
The following line of code at the end of
Most, if not all, modern C++ compilers will automatically insert
Finally, if you want a reliable
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 stdNever 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
stdand another namespace.
- Function conflicts between
stdand another namespace.
- Function conflicts between
stdand 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.