Comparer valeurs int et array

Résolu
Jockill
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019
- 25 mai 2018 à 09:52
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
- 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

12 réponses

cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
25 mai 2018 à 15:27
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.
0
Jockill
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

Modifié le 27 mai 2018 à 18:06
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 :)
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
27 mai 2018 à 20:45
La réponse est dans mon post précédent: std::find :)
0
Jockill
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

28 mai 2018 à 11:49
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;
}
...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
Modifié le 29 mai 2018 à 09:54
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
0
Dalfab
Messages postés
652
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
15 mai 2022
8
28 mai 2018 à 18:43
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;
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
29 mai 2018 à 10:04
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).
0
Jockill
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

30 mai 2018 à 17:09
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...
0
Jockill
Messages postés
102
Date d'inscription
jeudi 17 juillet 2014
Statut
Membre
Dernière intervention
13 mai 2019

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

30 mai 2018 à 17:13
A quoi correspond 0(1)?
0
Dalfab
Messages postés
652
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
15 mai 2022
8
30 mai 2018 à 17:23
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)
0
cptpingu
Messages postés
3834
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
20 octobre 2021
124
30 mai 2018 à 17:26
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;

0