TD03 : Gestion des Entrées/Sorties - Poésie Automatique

Objectif du TD : Réaliser un programme Java capable de générer et d'afficher aléatoirement des poèmes basés sur l'œuvre de Raymond Queneau, Cent mille milliards de poèmes. Le programme doit lire un fichier texte, stocker les vers en mémoire et les afficher graphiquement en respectant la structure du sonnet.

Partie 1 : Analyse du fichier et Combinatoire (Question 1)

Analyse de la structure du fichier Queneau.txt :

Calcul combinatoire :

Pour chaque ligne du poème, nous avons 10 choix possibles. Comme il y a 14 lignes indépendantes, le nombre total de combinaisons est :

10 × 10 × 10 ... (14 fois) = 1014

Cela correspond exactement au titre de l'œuvre : Cent mille milliards de poèmes.

Partie 2 : Lecture et Stockage (Questions 2 et 3)

Stockage en mémoire (Tableau 2D) :

Pour gérer efficacement ces données et permettre un accès aléatoire instantané (nécessaire pour la partie graphique), nous ne pouvons pas relire le fichier à chaque clic. Nous stockons donc tout le texte dans un tableau à deux dimensions de chaînes de caractères :

Déclaration Java : String tableau[][] = new String[14][10];

Code Modifié : AccesFichier.java

Ce code lit le fichier, ignore les lignes vides et les titres, et remplit le tableau structuré.

import java.io.*;

class AccesFichier
{
    // Tableau pour stocker les 140 vers (14 blocs de 10)
    String tableau[][] = new String[14][10];

    public AccesFichier() 
    {
        try 
        {
            FileReader fic = new FileReader("Queneau.txt");
            BufferedReader buf = new BufferedReader(fic);
            String chaine;
            
            int bloc = -1; // Indice du bloc (0-13)
            int vers = 0;  // Indice du vers dans le bloc (0-9)

            while ((chaine = buf.readLine()) != null)
            {
                // Si la ligne contient "Vers", on change de bloc
                if (chaine.startsWith("Vers")) {
                    bloc++;
                    vers = 0;
                }
                // Si c'est un vers valide (contient du texte et on est dans un bloc)
                else if (chaine.length() > 5 && bloc >= 0 && bloc < 14) {
                    // Nettoyage éventuel des numéros (ex: "1. Le roi...")
                    tableau[bloc][vers] = chaine;
                    vers++;
                }
            }
            fic.close();
        } 
        catch (IOException e) { 
            System.out.println("Erreur lecture : " + e); 
        }
    }
    
    // Accesseur pour fournir les données à l'interface graphique
    public String[][] getTableau() {
        return tableau;
    }

    public static void main(String argv[]) {
       new AccesFichier();
    } 
}

Partie 3 : Simulation Interactive et Affichage (Questions 3 et 4)

Logique de l'algorithme :

  1. Initialisation : Au lancement, le programme charge le fichier dans le tableau 2D via AccesFichier.
  2. Action Utilisateur : Un clic sur le bouton déclenche la méthode actionPerformed qui appelle repaint().
  3. Affichage (paint) :
    • On boucle 14 fois (pour les 14 lignes).
    • À chaque itération i, on tire un nombre aléatoire r entre 0 et 9.
    • On affiche le vers tableau[i][r].
    • Mise en page : Pour respecter la structure du sonnet (Quatrain / Quatrain / Tercet / Tercet), on ajoute un espacement vertical supplémentaire après les lignes 4, 8 et 11.
Java Applet / JFrame Simulation
Cent mille milliards de poèmes
Cliquez sur le bouton pour générer un poème...
Raymond Queneau
Fig 1. Simulation fonctionnelle. Cliquez sur le bouton pour tester l'algorithme aléatoire.

Code Complet Final : LancePoeme.java

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class LancePoeme extends JFrame implements ActionListener
{
    JButton bouton;
    AccesFichier fichier; 
    String[][] poemeData; // Référence vers le tableau 2D

    public LancePoeme()
    {
        super("Poésie automatique");
        setSize(500, 500);
        
        // 1. Chargement des données
        fichier = new AccesFichier();
        poemeData = fichier.getTableau();

        // 2. Interface
        bouton = new JButton("Afficher un nouveau poème");
        add(bouton, "North");
        bouton.addActionListener(this);
        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    
    // Déclencheur du rafraîchissement
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == bouton) {
            repaint(); // Force l'appel à paint()
        }
    }

    public void paint(Graphics g)
    {
        super.paintComponents(g); // Nettoie le fond

        // Titre
        g.setFont(new Font("Helvetica", Font.BOLD, 20));
        g.drawString("Cent mille milliards de poèmes", 60, 90);

        // Corps du poème
        g.setFont(new Font("Helvetica", Font.PLAIN, 13));
        
        int y = 125; // Ordonnée de départ
        
        // Boucle sur les 14 vers
        for (int i = 0; i < 14; i++) {
            
            // Logique aléatoire : choix entre 0 et 9
            int choix = (int)(Math.random() * 10);
            
            // Récupération sécurisée
            if (poemeData[i][choix] != null) {
                // Suppression des numéros "1. " si présents dans le fichier
                String vers = poemeData[i][choix].replaceAll("^\\d+\\.\\s*", "");
                g.drawString(vers, 60, y);
            }
            
            y += 15; // Interligne standard

            // Gestion des strophes (4 - 4 - 3 - 3)
            // Ajout d'espace après le 4ème, 8ème et 11ème vers
            if (i == 3 || i == 7 || i == 10) {
                y += 15;
            }
        }

        // Auteur
        g.setFont(new Font("Helvetica", Font.BOLD, 20));
        g.drawString("Raymond Queneau", 150, 430);
    }

    public static void main(String argv[])
    {
        new LancePoeme();
    } 
}