Comparer valeurs int et array [Résolu]

Jockill 83 Messages postés jeudi 17 juillet 2014Date d'inscription 8 juin 2018 Dernière intervention - 25 mai 2018 à 09:52 - Dernière réponse : cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention
- 30 mai 2018 à 17:26
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
Afficher la suite 

Votre réponse

12 réponses

cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention - 25 mai 2018 à 15:27
0
Merci
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.
Commenter la réponse de cptpingu
Jockill 83 Messages postés jeudi 17 juillet 2014Date d'inscription 8 juin 2018 Dernière intervention - Modifié par Jockill le 27/05/2018 à 18:06
0
Merci
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 :)
Commenter la réponse de Jockill
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention - 27 mai 2018 à 20:45
0
Merci
La réponse est dans mon post précédent: std::find :)
Commenter la réponse de cptpingu
Jockill 83 Messages postés jeudi 17 juillet 2014Date d'inscription 8 juin 2018 Dernière intervention - 28 mai 2018 à 11:49
0
Merci
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;
}
...
Commenter la réponse de Jockill
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention - Modifié par cptpingu le 29/05/2018 à 09:54
0
Merci
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
Commenter la réponse de cptpingu
Dalfab 342 Messages postés dimanche 7 février 2016Date d'inscription 20 juin 2018 Dernière intervention - 28 mai 2018 à 18:43
0
Merci
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;
Commenter la réponse de Dalfab
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention - 29 mai 2018 à 10:04
0
Merci
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).
Commenter la réponse de cptpingu
Jockill 83 Messages postés jeudi 17 juillet 2014Date d'inscription 8 juin 2018 Dernière intervention - 30 mai 2018 à 17:09
0
Merci
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...
Commenter la réponse de Jockill
Jockill 83 Messages postés jeudi 17 juillet 2014Date d'inscription 8 juin 2018 Dernière intervention - 30 mai 2018 à 17:12
0
Merci
Je vais essayer merci :)
Commenter la réponse de Jockill
Jockill 83 Messages postés jeudi 17 juillet 2014Date d'inscription 8 juin 2018 Dernière intervention - 30 mai 2018 à 17:13
0
Merci
A quoi correspond 0(1)?
Commenter la réponse de Jockill
Dalfab 342 Messages postés dimanche 7 février 2016Date d'inscription 20 juin 2018 Dernière intervention - 30 mai 2018 à 17:23
0
Merci
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)
Commenter la réponse de Dalfab
cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention - 30 mai 2018 à 17:26
0
Merci
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;

Commenter la réponse de cptpingu

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.