La fourmi de Langton
A propos du code
Les règles
Premier programme
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define BLACK Color(0, 0, 0)
#define WHITE Color(255, 255, 255)
int main(int argc, char* argv[])
{
// init the window
gfx.init("Langton's ant", SCREEN_WIDTH, SCREEN_HEIGHT);
gfx.init2D();
gfx.clearScreen(BLACK);
Ensuite, pour la fourmi, on aura besoin de sa position en x et en y et de sa direction.
int x = SCREEN_WIDTH / 2;
int y = SCREEN_HEIGHT / 2;
int dir = 0; // direction 0=up, 1=right, 2=down, 3=left
Ensuite, dans notre boucle principale, on teste si la fourmi est à l'intérieur de l'écran
// wait till the end
while (sys.isQuitRequested() == false)
{
// if we are on the screen
if (x >= 0 && x < SCREEN_WIDTH &&
y >= 0 && y < SCREEN_HEIGHT)
{
On récupère la couleur du pixel où est la fourmi
// get current color
Color c = gfx.getPixel(x, y);
On teste cette valeur pour tourner la fourmi et on change la couleur du pixel.
// turn and change color
if (c.argb == BLACK.argb)
{
dir = (dir - 1 + 4) % 4; // turn left
gfx.setPixel(x, y, WHITE);
}
else
{
dir = (dir + 1) % 4; // turn right
gfx.setPixel(x, y, BLACK);
}
Remarquez que pour les rotations on prend un modulo 4, parce que l'on veut une valeur entre 0 et 3.
// move forward
if (dir == 0)
{
y--; // up
}
else if (dir == 1)
{
x++; // right
}
else if (dir == 2)
{
y++; // down
}
else
{
x--; // left
}
}
Et on termine la boucle principale
sys.processEvents();
gfx.render();
sys.wait(2);
}
gfx.quit();
return EXIT_SUCCESS;
}
Télécharger le code source
Télécharger l'exécutable pour Windows
Regardons ce qui se passe quand on lance ce programme.
Ajouter plus de joueurs
int x[10];
int y[10];
int dir[10];
Color col[10];
On initialise ces valeurs aléatoirement.
srand(time(NULL));
for (int i = 0; i < 10; ++i)
{
x[i] = rand() % SCREEN_WIDTH;
y[i] = rand() % SCREEN_HEIGHT;
dir[i] = rand() % 4;
col[i] = Color(rand() & 0xff, rand() & 0xff, rand() & 0xff);
}
Et on les traite dans la boucle principale.
while (sys.isQuitRequested() == false)
{
for (int i = 0; i < 10; ++i)
lang(x[i], y[i], dir[i], col[i]);
sys.processEvents();
gfx.render();
sys.wait(2);
}
La fonction lang() contient le code qu'on a déjà vu avec seulement une petite modification pour la couleur.
void lang(int &x, int &y, int &dir, Color& col)
{
// if we are on the screen
if (x >= 0 && x < SCREEN_WIDTH &&
y >= 0 && y < SCREEN_HEIGHT)
{
// get current color
Color c = gfx.getPixel(x, y);
// turn and change color
if (c.argb == BLACK.argb)
{
dir = (dir - 1 + 4) % 4; // turn left
gfx.setPixel(x, y, col);
}
else
{
dir = (dir + 1) % 4; // turn right
gfx.setPixel(x, y, BLACK);
}
// move forward
if (dir == 0)
{
y--; // up
}
else if (dir == 1)
{
x++; // right
}
else if (dir == 2)
{
y++; // down
}
else
{
x--; // left
}
}
}
Télécharger le code source
Télécharger l'exécutable pour Windows
Si vous lancez ce programme plusieurs fois, vous verrez des comportements intéressants.
Ajouter des couleurs
char rule[] = "RLR";
int nbColors = strlen(rule);
On va utiliser une palette pour ces couleurs. Elle sera initialisée avec des couleurs aléatoires à part la couleur
Color* palette;
// init palette
srand(time(NULL));
palette = new Color[nbColors];
palette[0] = Color(0, 0, 0);
for (int i = 1; i < nbColors; i++)
{
palette[i] = Color(rand() % 256,
rand() % 256,
rand() % 256);
}
Comme ça ne serait pas facile de retrouver le numéro d'une couleur à partir de sa valeur RVB comme on le faisait
int world[SCREEN_WIDTH][SCREEN_HEIGHT];
// init world
for (int yy = 0; yy < SCREEN_HEIGHT; yy++)
for (int xx = 0; xx < SCREEN_WIDTH; xx++)
world[xx][yy] = 0;
Ensuite, dans la boucle principale, on va d'abord récupérer la couleur où la fourmi est
// wait till the end
while (sys.isQuitRequested() == false)
{
// if we are on the screen
if (x >= 0 && x < SCREEN_WIDTH &&
y >= 0 && y < SCREEN_HEIGHT)
{
// get current color
int c = world[x][y];
On décide de tourner à gauche ou à droite en fonction de la lettre de la règle qui correspond à cette couleur:
// turn
if (rule[c] == 'R')
{
dir = (dir + 1) % 4; // turn right
}
else
{
dir = (dir - 1 + 4) % 4; // turn left
}
Pour changer la couleur de la case, dans le monde bicolore on transformait une cellule noire en blanche et vice
// change color
c = (c + 1) % nbColors;
world[x][y] = c;
gfx.setPixel(x, y, palette[c]);
Et on avance...
// move forward
if (dir == 0)
{
y--; // up
}
else if (dir == 1)
{
x++; // right
}
else if (dir == 2)
{
y++; // down
}
else
{
x--; // left
}
}
Download source code
Download executable for Windows
Comme les fourmis sont plus complexes maintenant, on va obtenir différents résultats en fonction de la règle qu'on a