Partage
  • Partager sur Facebook
  • Partager sur Twitter

Variables à noms dynamiques

Ou autres solutions convenant au besoin présenté

Sujet résolu
    20 juillet 2016 à 13:24:49

    Bonjour.

    Je suis débutant en programmation, je souhaiterais dans l'un de mes programmes, déclarer des variables avec des noms dynamiques. Je vous explique rapidement la situation (beaucoup simplifiée) : l'utilisateur peut rentrer autant de "fiches" qu'il veut. Ces "fiches" sont des objets ayants plusieurs variables justement défini par l'utilisateur. Cependant je ne trouve pas comment nommer ces variables automatiquement, du genre "personne1", "personne2", etc. ... j'ai fait de nombreuses recherches sur internet, et j'ai trouvé que les variables dynamiques seraient parfaites dans ces situations. Cependant j'ai aussi compris que cela était impossible dans java, et qu'il fallait passer par des tableaux, où d'autres trucs dont je ne cerne pas la différence. Je n’ai pas réussi à reproduire les solutions donné. Je suis conscient que la solution est simple mais je n'y arrive vraiment pas.

    Pourriez-vous m'aidez s'il vous plaît ? Je suis ouvert à toute solutions, même si elles impliquent de revoir toute ou partie du code.

    Voici un extrait du code :

    static void Load(){	//il s’agit dans ce cas d’un lecteur qui va ouvrir une sauvegarde.
    	try{
    		InputStream Input = new FileInputStream("Sauvegarde.txt");
    		InputStreamReader InputReader = new InputStreamReader(Input);
    		BufferedReader buffer = new BufferedReader(InputReader);
    		try {
    			Counter.Nombre = Integer.parseInt(buffer.readLine());	
    			for(int x = 1; x <=Counter.GetNumber(); x++){
    				//j’aimerais générer un mot diffèrent à chaque fois que la boucle fait un tour
    				Player x = new Player(buffer.readLine(), buffer.readLine(), buffer.readLine(), buffer.readLine(), buffer.readLine(), Boolean.parseBoolean(buffer.readLine()), Integer.parseInt(buffer.readLine()), Integer.parseInt(buffer.readLine()));
    // J’ai essayé de réutiliser cette boucle en utilisant ses nombres, sans succès.
    			}
    				
    		}catch (NumberFormatException | IOException e) {
    			e.printStackTrace();
    		}
    	}catch (FileNotFoundException e){
    		e.printStackTrace();
    	}
    


    -
    Edité par ErwanRenault 20 juillet 2016 à 13:29:22

    • Partager sur Facebook
    • Partager sur Twitter
      20 juillet 2016 à 13:50:11

      Je ne pense pas que ça soit possible, et si ça l'est je trouve ça abominable... Tu ne gérerais plus du tout le nom de tes variables. 

      L'idéal dans ton cas serait de faire une ArrayList de Player, à déclarer comme ceci : 

      List<Player> players = new ArrayList<Player>();

      Du coup dès que ton utilisateur rentre une fiche tu n'as plus qu'à faire : 

      players.add(new Player(...)); 

      Si la fiche doit être nommée tu peux aussi faire une HashMap comme ceci :

      Map<String, Player> players = new HashMap<String, Player>(); 

      Tu auras donc des players identifiés par une string (leur nom). Et pour ajouter des joueurs dans la liste c'est comme ça : 

      players.put("Personne 1", new Player(...));
      
      

      Je suis presque sûr de moi pour la syntaxe mais si ça ne fonctionne pas je t'encourage à aller voir la documentation: 

      - ArrayList

      - HashMap

      Tu peux aussi poser des questions ici si besoin hein :D En espérant t'avoir aidé ! 

      EDIT: Avec un peu d'explication c'est mieux... Une ArrayList tu peux la voir comme un tableau mais en beaucoup plus pratique. Tu peux ajouter des objets dedans et les récupérer pour traitement. Cependant, tu devras peut être écrire une méthode ou deux pour gérer les données présentent (récupération, etc.) C'est le plus pratique pour faire des opérations sur des objets que tu dois stocker. 

      La HashMap quant à elle stocke des objets en mode KEY VALUE. En gros tous les objets présent dans une hashmap on un "nom". Si on prend pour exemple un tableau, les valeurs (objets) présentent dedans sont identifiées par l'indice de la case (1, 2, etc.) alors que la tu vas donner une valeur, (un Integer, String, comme tu veux) pour identifier ton objet ou ta valeur.  

      EDIT 2: OUAH TROP DE MODIFICATION... J'ai oublié de préciser, en fonction de tes besoins tu devras placer la liste/map dans la méthode ou alors dans la classe. A toi de voir la durée de vie que tu veux pour ta liste/map :) 



      -
      Edité par Skaizer 20 juillet 2016 à 13:57:50

      • Partager sur Facebook
      • Partager sur Twitter
        20 juillet 2016 à 14:26:59

        Merci pour ta réponse, je l'enregistre quelque part, ça me resservira. J'ai préféré utiliser la première solution, et elle convient parfaitement. Seulement, comment on extrait une fiche maintenant ? Il y a bien le ".indexof()", mais je ne peux plus accéder aux valeurs de mes fiches. Je m'explique je voudrais maintenant pouvoir faire :

        "Counter.Players.indexOf(1).get_uuid"

        Counter est l'endroit où j'ai mis la variable en static (Je crois que c'est comme ça que l'on doit faire), 1 serait la 2ème fiche (puisque si j'ai bien suivi, l'indexation commence à 0) et get_uuid une fonction (méthode) de Player

        • Partager sur Facebook
        • Partager sur Twitter
          20 juillet 2016 à 14:59:48

          Si tu veux extraire toutes les fiches il faut utiliser une boucle For sur ta liste : 
          for(Player p : players) {
          //Tu récupères la valeur que tu veux en utilisant p (le Player sur lequel tu es). 
          }

          Si tu veux un utilisateur en particulier il faut utiliser un critère précis. Par exemple si tu veux la fiche qui s'appelle "Fiche 1": 

          for(Player p : players) {
          if(p.get_name().equals("Fiche 1"){
          //Tu récupères la valeur que tu veux.
          break; //Pour sortir du for si je ne me trompe pas. 
          }
          }

          Après si tu as besoin d'identifier tes players et de les récupérer plus simplement une map serait plus appropriée :)

           EDIT: get_name() est une méthode qu'il faut écrire ou que tu as déjà dans ta classe Player. C'est le getter qui retourne le nom de ta fiche (du player). 

          -
          Edité par Skaizer 20 juillet 2016 à 15:01:02

          • Partager sur Facebook
          • Partager sur Twitter
            20 juillet 2016 à 15:07:07

            Bonjour,

            indexOf retourne l'index d'un élément. C à d que tu lui donnes un Player et ça te donne sa position dans la list. Pour récupérer un Player à partir de son index, c'est la méthode get.

            Player player = Counter.players.get(i);

            Sinon, si tu veux faire une action sur tous les Player, il vaut mieux utiliser une boucle for-each.

            for (Player player : Counter.players) { // pour chaque Player de la liste
                // faire quelque chose
            }




            • Partager sur Facebook
            • Partager sur Twitter
              20 juillet 2016 à 15:41:33

              je pense que je m'y prendre mal, après que les fiches aient été extraits du fichier et vu qu'elles n'ont plus de nom, je n'arrive pas à accéder à leurs méthodes (qui ressemblent à ça : "public String GetPseudo(){return this.Pseudo;}" et qui sont dans la class « player ».

              La « arrArrayList » quant à elle se trouve dans une autre class (« counter ») parce que je sinon, chaque fiche aurais une liste de fiche et ce serait le bazar.

              Dans une troisième classe (qui me sert de test), dans le « main », je créé des fiches, je sauvegarde, puis je les extraits (pour simuler le démarrage de l'application), et là je veux pouvoir accéder aux donné que je viens d'extraire.

              Beaucoup de méthodes que j’ai créé requière l’objet pour fonctionner, est-il possible de créer une variable contenant ma fiche ?

              C’est quoi la durée de vie ? Mes fiches disparaissent à un moment ?

              Edit1 :

              En utilisant la commande :

              Counter.Players.get(0).GetPseudo()

              voici l'erreur qui ressort :

              Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
                  at java.util.ArrayList.rangeCheck(Unknown Source)
                  at java.util.ArrayList.get(Unknown Source)
                  at test1.MyClass.main(MyClass.java:193)

              -
              Edité par ErwanRenault 20 juillet 2016 à 15:50:00

              • Partager sur Facebook
              • Partager sur Twitter
                20 juillet 2016 à 15:51:06

                Je ne comprend pas trop l'utilité de ta classe Counter... Si tu dois extraire les informations de ton fichier tu n'as besoin que de deux classes techniquement, un main et ta classe Player (qui sera utilisé pour stocker les informations de ton fichier). 

                Dans ton main tu ouvres et tu lis ton fichier, pour chaque ligne (je sais pas trop comment ton fichier est construit) tu crées un objet Player que tu ranges dans ton ArrayList. Par exemple si ton constructeur de Player ressemble à ça : 

                //Dans la classe Player
                public Player (String pseudo, int age) { 
                this.pseudo = pseudo; 
                this.age = age; 
                }

                Alors il te suffira de créer ton objet comme ça: 

                //Dans ta classe principale 
                Player p = new Player(info fichier pseudo, info fichier age);
                //Ensuite tu l'affectes à ton ArrayList comme ça 
                players.add(p); 

                Si ta liste est déclarée dans ta classe principale alors elle aura la durée de vie de ton application. 

                Tu peux montrer un bout de ton fichier txt pour qu'on puisse aider un peu plus? 

                EDIT: players étant le nom de ta liste il ne faut pas mettre de majuscule au début de ta variable... Pour ce qui est de ton erreur il t'indique qu'il ne connait pas ta liste et que du coup l'index 0 est en dehors de ce qu'il a (vu qu'il n'a rien xD ) 

                -
                Edité par Skaizer 20 juillet 2016 à 15:53:12

                • Partager sur Facebook
                • Partager sur Twitter
                  20 juillet 2016 à 16:24:27

                  Je met toutes les variables static dans counter (c'est pour m'y retrouver)

                  C'EST BON CA MARCHE !!!

                  je m'était embrouillé entre les variables Players, player et players

                  Merci 1000 fois ^^

                  -
                  Edité par ErwanRenault 20 juillet 2016 à 16:24:47

                  • Partager sur Facebook
                  • Partager sur Twitter
                    20 juillet 2016 à 16:45:10

                    Théoriquement je pense que ca doit être faisable, je ferai un test un jour pour voir.

                    En faisant un truc du genre :

                    - Une classe EnsemblePlayer.

                    - Utiliser une librairie qui s'appelle javassist (qui permet le changement de contenu d'une classe à l’exécution).

                    for(int x = 1; x <=Counter.GetNumber(); x++){
                    CtClass ensemblePlayer = ClassPool.getDefault().get("EnsemblePlayer");
                    CtField f = new CtField(ClassPool.getDefault().get("Player", "player"+x, ensemblePlayer );
                    point.addField(f);
                    }

                    => j'ai ajouté des champs playerX (où x est dynamique) dans la classe EnsemblePlayer

                    - Ajouter les getters et setter (il faudra probablement utiliser un peu de reflexion)

                    - Peut être qu'il faudra recharger la classe EnsemblePlayer avec un ClassLoader spécifique

                    - Et enfin accéder en utilisant de la reflexion. ClassLoader.forName("Ensemble...").getField("player1") pour accéder à la variable player1

                    C'est moche, c'est inutile, c'est inmaintenable car incompréhensible mais ça doit être faisable.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 juillet 2016 à 12:17:22

                      C'est justement parce que c'est moche qu'il faut éviter de faire ce genre de chose xD Il y a des possibilités existantes avec JAVA pour faire ce genre de chose "proprement". 

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Variables à noms dynamiques

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown