Créer un tableau dont chaque élément est associé à un bloc de 30 degrés:
Car::EDirection dirlist[] = {
Car::EDirection::RIGHT,
Car::EDirection::UP_RIGHT,
Car::EDirection::UP,
Car::EDirection::UP,
Car::EDirection::UP_LEFT,
Car::EDirection::LEFT,
Car::EDirection::LEFT,
Car::EDirection::DOWN_LEFT,
Car::EDirection::DOWN,
Car::EDirection::DOWN,
Car::EDirection::DOWN_RIGHT,
Car::EDirection::RIGHT
};
Ensuite, vous pouvez l'indice de la matrice avec l'angle / 30:
this->_car.edir = dirlist[(this->_car.getAbsoluteAngle() % 360) / 30];
Pas de comparaison ou de branchement nécessaire.
Le résultat est cependant légèrement hors de l'original. Les valeurs sur les frontières, c'est à dire 30, 60, 120, etc. sont placés dans la catégorie suivante. Par exemple, dans le code d'origine les valeurs valides pour UP_RIGHT
de 31 à 60. Le code ci-dessus affecte 30 à 59 UP_RIGHT
.
On peut contourner ce problème en soustrayant 1 de l'angle:
this->_car.edir = dirlist[((this->_car.getAbsoluteAngle() - 1) % 360) / 30];
Cela nous offre maintenant RIGHT
de 30, UP_RIGHT
pour 60, etc.
Dans le cas de 0, l'expression devient (-1 % 360) / 30
. Ceci est valable parce qu' -1 % 360 == -1
et -1 / 30 == 0
, de sorte que nous obtenons toujours un indice de 0.
L'article 5.6 de la norme C++ confirme ce comportement:
4 Le binaire /
opérateur donne le quotient et le binaire %
opérateur donne le reste de la division de la première
l'expression par le second. Si le second opérande de /
ou %
est égal à zéro
le comportement est indéfini. Intégrale de la opérandes l' /
de l'opérateur
les rendements de la algébrique quotient avec toute partie fractionnaire jeté. si
le quotient a/b
est représentable dans le type du résultat,
(a/b)*b + a%b
est égal à a
.
EDIT:
Il y avait beaucoup de questions soulevées au sujet de la lisibilité et la maintenabilité d'une construction de ce genre. La réponse donnée par motoDrizzt est un bon exemple de la simplification de l'original de la construction qui est plus facile à gérer et n'est pas aussi "laid".
L'expansion sur de sa réponse, voici un autre exemple, l'utilisation de l'opérateur ternaire. Puisque chaque cas dans le post original est d'attribuer à la même variable, à l'aide de cet opérateur peut aider à augmenter la lisibilité d'autres.
int angle = ((this->_car.getAbsoluteAngle() % 360) + 360) % 360;
this->_car.edir = (angle <= 30) ? Car::EDirection::RIGHT :
(angle <= 60) ? Car::EDirection::UP_RIGHT :
(angle <= 120) ? Car::EDirection::UP :
(angle <= 150) ? Car::EDirection::UP_LEFT :
(angle <= 210) ? Car::EDirection::LEFT :
(angle <= 240) ? Car::EDirection::DOWN_LEFT :
(angle <= 300) ? Car::EDirection::DOWN:
(angle <= 330) ? Car::EDirection::DOWN_RIGHT :
Car::EDirection::RIGHT;