automate cellulaire : compter les voisins

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Salut,
Je fait un automate cellulaire (conway’s game of life) Il fonctionne assez bien, mais sur les bords de la fenêtre je veux que les cellules considèrent que en dehors du cadre il y a des cellules vivantes.

je fais donc auto v = grid.countNeighbours(0, 0);
En sachant que les coordonnées avec(x;y) : (-1;-1) (-1;0) (-1; 1) (0;-1) (1;-1) sont en dehors du cadre et devraient donc resortir vivante.
Mais v vaut 0 ce qui est faux il devrait valoir 5.

Voici mon code pour calculer les voisins:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
size_t Grid::countNeighbours(const size_t &x, const size_t & y) const {
  
  
  int cpt = 0;
  int loop1 = 0;
  int loop2 = 0;
 
  for(int i = x-1; i < (x+2); i++ ){
      
      loop1++;
      for(int j = y-1; j < (y+2); j++){
          loop2++;
          if(isAlive(i, j))
              cpt++;              
              
      }
  }
  if(isAlive(x, y)) //dans le carré compté la cellule centre est vivante, on la dé-compte
      cpt--;
  
  return cpt;
  
  
 }

et mon isAlive:

1
2
3
4
5
6
7
8
bool Grid::isAlive(const long long int &x, const long long int &y) const{
  try {
      return m_grid.at(y).at(x) == Grid::State::ALIVE ;
      //m grid est std::array<std::array<State, 100>, 100> 
  } catch (std::out_of_range& e) {
      return true; //hors du cadre = considéré comme vivant
  }
 }

Ce que je remarque au debugger c’est que loop1 et loop2 valent toujours 0. Comme si on ne rentrait pas dans les boucle, il se peut que ce soient à cause de x et y qui sont size_t (unsigned) et que le x-1 : 0-1 ne soit pas accepté J’aimerais savoir pourquoi j’observe ce comportement, s’il est normal et comment avoir le comportement escompté

EDIT: voici ce que j’obtient après ~12 (je me suis tromper en comptant, mais j’ai la flemme de recompter) iterationspb automate cellulaire

Comme on peut le voir seul les partie avec x et y > 100 (hors cadre) sont considérés comme des cellules vivantes alors que j’aimerais que ça fasse ça avec tous les cotés

Édité par d3m0t3p

conseil: le thé est meilleur avec un zeste de citron

+0 -0

Cette réponse a aidé l’auteur du sujet

Tu as un mélange d’entiers signés (int, long long int) et d’entiers non signés (size_t). Je serais pas étonné que le problème vienne de là.

Au passage, tu ne devrais pas utiliser des exceptions pour quelque chose de normal, dans ton cas voir si une case est en dehors du cadre. Comme leur nom l’indique, ce sont des exception. Tu peux simplement les remplacer par un test avant d’accéder à ton point.

+1 -0
Banni

Au passage, tu ne devrais pas utiliser des exceptions pour quelque chose de normal, dans ton cas voir si une case est en dehors du cadre. Comme leur nom l’indique, ce sont des exception. Tu peux simplement les remplacer par un test avant d’accéder à ton point.

Berdes

Je suis pour l’utilisation des exceptions ici pour palier à un manque du langage. :P Si on effectue un test, au final on se sera fatigué à coder un truc déjà fait par l’appel à at. (Dans un autre langage on se placerait dans la monade Maybe pour faire nos appels et ensuite on remplacerait la valeur « poubelle » Nothing par True.)

+2 -0
Auteur du sujet

Tu as un mélange d’entiers signés (int, long long int) et d’entiers non signés (size_t). Je serais pas étonné que le problème vienne de là.

Berdes

C’est bien ça,

Mais je considère que size_t est le bon type pour representer un index puisqu’il ne peut pas exister d’index négatif, quant au fait que unsigned - signed me donne un unsigned je trouve ça illogique et j’aimerais un moyen me permettant de garder mes paramètres de type size_t même si lors du calcule je dois dire explicitement de produire un résultat pouvant être négatif.

Pour ce qui est du try-catch, je considère que la méthode at() gère les index hors cadre, je vais pas à nouveau gérer moi-même les cas hors cadre. Je fais juste attention aux exceptions renvoyéee par at et ça suffit je trouve, après c’est une question de gout je penses entre if/try-catch

conseil: le thé est meilleur avec un zeste de citron

+0 -0

quant au fait que unsigned - signed me donne un unsigned je trouve ça illogique et j’aimerais un moyen me permettant de garder mes paramètres de type size_t même si lors du calcule je dois dire explicitement de produire un résultat pouvant être négatif.

d3m0t3p

il faut static_cast ton size_t en (long) int. (voire vers make_signed<size_t>::type). Et pour ce qui est des étrangetés avec unsigned, merci les conversions implicites venant du C.

Une guideline (venant de Stroustrup) à suivre est "ne jamais faire de maths avec une variable unsigned"

Édité par minirop

+1 -0
Auteur du sujet

il faut static_cast ton size_t en (long) int. Une guideline (venant de Stroustrup) à suivre est "ne jamais faire de maths avec une variable unsigned"

minirop

Okok, merci du conseil

conseil: le thé est meilleur avec un zeste de citron

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte