/* Définition de la classe cellmap, constructeur, copy_cells(), set_cell(), clear_cell(), cell_state(), count_neighbors(), et next_generation() pour une approche rapide et câblée des voisines. Sinon, semblable au Listing 17-1. */ class cellmap { private: unsigned char *cells; unsigned int width; unsigned int width_in_bytes; unsigned int height; unsigned int length_in_bytes; public: cellmap(unsigned int h, unsigned int v); ~cellmap(void); void copy_cells(cellmap &sourcemap); void set_cell(unsigned int x, unsigned int y); void clear_cell(unsigned int x, unsigned int y); int cell_state(int x, int y); int count_neighbors(int x, int y); void next_generation(cellmap& dest_map); }; /* Constructeur de l'objet cellmap. Remplit autour de la zone de stockage de cellules avec 1 octet supplémentaire, utilisé pour le bouclage des bords. */ cellmap::cellmap(unsigned int h, unsigned int w) { width = w; width_in_bytes = ((w + 7) / 8) + 2; // remplit chaque bord // avec 1 octet supplémentaire height = h; length_in_bytes = width_in_bytes * (h + 2); // remplit le haut et le bas // avec 1 octet supplémentaire cells = new unsigned char[length_in_bytes]; // stockage des cellules memset(cells, 0, length_in_bytes); // rend les cellules inactives au démarrage } /* Copie une carte de cellules dans une autre. Si le bouclage est activé, copie les octets des bords sur le coté opposé. Ces deux cartes de cellules sont supposées être de même taille. */ void cellmap::copy_cells(cellmap &sourcemap) { unsigned char *cell_ptr; int i; #if WRAP_EDGES // Copie les bords droit et gauche dans les octets de remplissage à droite et à gauche cell_ptr = sourcemap.cells + width_in_bytes; for (i=0; i> (x & 0x07); } /* Désactive une cellule. x et y sont décalés de 1 octet en bas et à droite, pour compenser les octets de remplissage autour de la carte de cellules. */ void cellmap::clear_cell(unsigned int x, unsigned int y) { unsigned char *cell_ptr = cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1); *(cell_ptr) &= ~(0x80 >> (x & 0x07)); } /* Retourne l'état de la cellule (1=actif or 0=inactif). x et y sont décalés de 1 octet en bas et à droite, pour compenser les octets de remplissage autour de la carte de cellules. */ int cellmap::cell_state(int x, int y) { unsigned char *cell_ptr = cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1); return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0; } /* Compte le nombre de voisines actives d'une cellule spécifiée. */ int cellmap::count_neighbors(int x, int y) { unsigned char *cell_ptr, mask; unsigned int neighbor_count; // Pointe sur la voisine en haut à gauche cell_ptr = cells + ((y * width_in_bytes) + ((x + 7) / 8)); mask = 0x80 >> ((x - 1) & 0x07); // Compte la voisine en haut à gauche neighbor_count = (*cell_ptr & mask) ? 1 : 0; // Compte la voisine de gauche if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++; // Compte la voisine en bas à gauche if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++; // Pointe sur la voisine du dessus if ((mask >>= 1) == 0) { mask = 0x80; cell_ptr++; } // Coompte la voisine du dessus if ((*cell_ptr & mask)) neighbor_count++; // Compte la voisine du dessous if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++; // Pointe sur la voisine en haut à droite if ((mask >>= 1) == 0) { mask = 0x80; cell_ptr++; } // Compte la voisine en haut à droite if ((*cell_ptr & mask)) neighbor_count++; // Compte la voisine de droite if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++; // Compte la voisine en bas à droite if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++; return neighbor_count; } /* Calcule la prochaine génération de current_map et la stocke dans next_map. */ void cellmap::next_generation(cellmap& next_map) { unsigned int x, y, neighbor_count; for (y=0; y