Comparer valeurs int et array [Résolu]

Signaler
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019
-
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
-
Bonjour,
je crée un système de déplacement en c++ dans lequel un personnage évolue dans une carte représentée par des cases numérotées (comme les cartes de randonnée par exemple).
Le problème est que sur sa route se trouvent des cases inaccessibles.
J'ai ca pour le moment :

    int valeursInterdites[5] = {1 ,2 ,3 ,4 ,5};
    int position = 6;

    char sensMouvement;
    cout << "Dans quelle direction voulez-vous vous deplacer ?" << endl << "(N,S,E,O)" << endl; 
    cin >> sensMouvement; 

    do {
        switch(sensMouvement){

        case 'N':
            direction = nord;
            position = position+10;
            //SI POSITION INCLUSE DANS valeursInterdites ALORS ERRORMVT SINON ON CONTINUE
            errorMvt(); // FONCION ENVOYANT UN MESSAGE D'ERREUR A L'UTILISATEUR
            mvtCheck = false; 
        break;

        ...
        
        }
    }while(mvtCheck==false);


Est ce que quelqu'un aurait une idée ?
J'ai essayé d'utiliser std::begin et std::end mais elles ne semblent pas fonctionner, je ne pense pas utiliser c++11

Merci énormément !
JøckIll

12 réponses

Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Bonjour.

Je ne comprends pas bien ta question. Pas facile de t'aider :(. Quel est ton souci ? Est-ce trouver une valeur actuelle dans un tableau (std::find) ? Est-ce trouver une série de valeur dans un tableau (std::find_if) ?

Quelques remarques:
- Evite les "using namespace", c'est ultra dégueux, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace/
- Utilise C++11 si tu as le choix (meilleure performance, meilleurs rapports d'erreurs, plein de choses en plus, pas mal d'outils simplifiés, et pas d'obligation de changer de syntaxe). Aucune raison de se brider donc !
- Si tu as besoin de faire un tableau fixe qui ne change jamais de taille, utilise plutôt un std::array (qui possède begin et end) au lieu d'un tableau "C".
- Si ton but est de vérifier qu'un élément n'est pas dans une collection, alors ce n'est pas du tout un tableau qu'il te faut, mais un std::set (voir même un std::unordered_set !)
- Un booléen se compare plutôt comme suit: "while (!mvtCheck)". On évite de faire "bool == true/false", c'est assez redondant.
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

Bonjour !
Desole pour la reponse tardive ^^'
En gros ma question est : comment est ce que je peux faire pour voir si ma variable int est incluse dans mon array.
Du coup faire quelquechose du type

if (MaVariable == NimporteQuelleValeurDuTableau) ...


Je vais aller jeter un oeil aux std::set
Merci :)
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
La réponse est dans mon post précédent: std::find :)
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

Salut
jai été voir sur cpp ref mais je n'ai pas tres bien compris la syntaxe de std::find ...
j'aurais du coup :

int interdites[5]  {1 ,2 ,3 ,4 ,5};
int position;
...
int posInterdite = std::find(std::begin(interdites), std::find(interdites), pi);
if (position == pi) {
cout << "Position interdite" << endl;
}
...
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Voici 4 manières différentes de faire les choses:
#include <iostream>
#include <array>
#include <vector>
#include <set>
#include <unordered_set>

int main()
{
  int position = 3;

  // Moche, mélange C et C++
  int interdites[5] = {1 ,2 ,3 ,4 ,5};
  auto found = std::find(std::begin(interdites), std::end(interdites), position);
  if (found != std::end(interdites))
    std::cout << "Position interdite trouvée" << std::endl;
  else
    std::cout << "Position interdite NON trouvée" << std::endl;

  // Mieux, si tu sais que ton tableau ne changera jamais de taille
  std::array<int, 5> interdites2 = {1 ,2 ,3 ,4 ,5};
  auto found2 = std::find(interdites2.begin(), interdites2.end(), position);
  if (found2 != interdites2.end())
    std::cout << "Position interdite trouvée" << std::endl;
  else
    std::cout << "Position interdite NON trouvée" << std::endl;

  // Si ton tableau peut changer de taille
  std::vector<int> interdites3 = {1 ,2 ,3 ,4 ,5};
  auto found3 = std::find(interdites3.begin(), interdites3.end(), position);
  if (found3 != interdites3.end())
    std::cout << "Position interdite trouvée" << std::endl;
  else
    std::cout << "Position interdite NON trouvée" << std::endl;

  // Si tu veux savoir si un élément n'est pas dans une série, un set est plus adapté
  // (un ordre de grandeur plus rapide, de l'ordre de 0(log(n)) au lieu de 0(n) pour un tableau).
  std::set<int> interdites4 = {1 ,2 ,3 ,4 ,5};
  if (interdites4.find(position) != interdites4.end())
    std::cout << "Position interdite trouvée" << std::endl;
  else
    std::cout << "Position interdite NON trouvée" << std::endl;

  // La version la plus rapide, mais plus "gourmande" en mémoire
  // (ordre de grandeur de l'ordre de 0(1)).
  std::unordered_set<int> interdites5 = {1 ,2 ,3 ,4 ,5};
  if (interdites5.find(position) != interdites5.end())
    std::cout << "Position interdite trouvée" << std::endl;
  else
    std::cout << "Position interdite NON trouvée" << std::endl;


  return 0;
}


A noter que ce que tu sembles vouloir faire, ne nécessite normalement pas de chercher si un élément est présent dans un ensemble. Si tu as une grille représentant une carte, alors il suffit de regarder au coordonnées si un obstacle est présent. Je réponds techniquement à ta question, mais je doute que tu partes dans la bonne direction.


Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
555
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
14 mai 2021
5
Il existe même d'autres possibilités, en particulier si la liste à parcourir est naturellement triée (est un peu plus rapide que les précédentes si y a une grande quantité de données.)
  std::vector<int> interdites5{ 1 ,2 ,3 ,4 ,5 }; // ou tableau ou array<> trié
  auto found5 = std::lower_bound( begin(interdites5), end(interdites5), position );
  if ( found5!=interdites5.end()  &&  *found5==position )
    std::cout << "Position interdite trouvée" << std::endl;
  else
    std::cout << "Position interdite NON trouvée" << std::endl;
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Merci Dalfab, je n'y avais pas pensé :) (Ta deuxième vérification n'est normalement pas nécessaire).

J'ai aussi ajouté le std::unordered_set (hash set) qui est encore plus rapide que tout cela (mais au détriment de la mémoire). Il existe une dernière solution, si on ne fait que rechercher des entiers relativement contigus, avec un std::array "troué" contenant des booléen. C'est le même principe que le std::unordered_set mais on ne "paie" pas la fonction de hash (car l'index est direct).
Enfin, si on veut à la fois de la vitesse et peu d'espace mémoire pris, on partira sur un "bloom filter", (pour le prix de 3 à 4 fonctions de hash, on peut retrouver un élément en 0(1) dans un set binaire très petit).
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

Salut
J'ai pensé aux coordonnees mais ça a été plus simple pour moi de numéroter les cases parce que j'avais pas vraiment d'idée sur comment mettre ça en place...
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

Je vais essayer merci :)
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

A quoi correspond 0(1)?
Messages postés
555
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
14 mai 2021
5
o(1) : c'est une notation mathématique pour indiquer que l'élément est trouvé en temps constant.
Les autres méthodes sont:
  • en o(Log n) : très rapide (méthodes 4, 5, 6)
  • en o(n) : rapide (méthodes 1, 2 et 3)
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
A quoi correspond 0(1)?

https://fr.wikipedia.org/wiki/Analyse_de_la_complexit%C3%A9_des_algorithmes

J'ai pensé aux coordonnees mais ça a été plus simple pour moi de numéroter les cases parce que j'avais pas vraiment d'idée sur comment mettre ça en place...

Si tu as une carte, tu as forcément une grille, et donc un tableau à double dimension (ou un tableau à simple dimension qui se comporte comme un double). A ce moment, l'accès à une case est aisé.

Soit une grille de 4x5.

Avec un tableau double:
    std::array<std::array<char, 5>, 4> grid;
    // Init toutes les cases à "."
    for (int i = 0; i < 4; ++i)
      for (int j = 0; j < 5; ++j)
        grid[i][j] = '.';
    // tout en haut à gauche
    grid[0][0] = '#';
    // tout en bas à droite
    grid[3][4] = '#';
    // Affichage de la grille
    for (int i = 0; i < 4; ++i)
    {
      for (int j = 0; j < 5; ++j)
        std::cout << grid[i][j];
      std::cout << std::endl;
    }
    std::cout << std::endl;


Avec un tableau simple:
    std::array<char, 5*4> grid;
    // Init toutes les cases à "."
    for (int i = 0; i < 5*4; ++i)
        grid[i] = '.';
    // tout en haut à gauche
    grid[0 * 4 + 0] = '#';
    // tout en bas à droite
    grid[3 * 4 + 4] = '#';
    // Affichage de la grille
    for (int i = 0; i < 4; ++i)
    {
      for (int j = 0; j < 5; ++j)
        std::cout << grid[i * 4 + j];
      std::cout << std::endl;
    }
    std::cout << std::endl;