• Aucun résultat trouvé

Licence Info 3éme année - module

N/A
N/A
Protected

Academic year: 2022

Partager "Licence Info 3éme année - module"

Copied!
6
0
0

Texte intégral

(1)

Licence Info 3éme année - module Programmation Objet 2 Examen – janvier 2018 – session 1 – durée : 2h

Documents autorisés : les polycopiés du cours (pas de TD/TP)

Partie A : Programmation graphique (environ 10 points)

L’objectif est de créer une interface avec MVC pour simuler un jeu de devination d’un password codé sous forme de n bits dont la valeur est 0 ou 1.

L’interface est donnée ci-dessous, où le nombre de bits saisi est 3, le bouton «Set a password » permet de gérer au hazard un entier (110) entre 0 et 2^3 comme password, et l’utilisateur fait une proposition, si cette proposition est bonne, la vérification va afficher « Yes » ; sinon

« No ».

Question A.1 :

Qu’est-ce que le design pattern MVC ? Définir le MVC pour cet exercice.

Question A.2 : Coder ce MVC.

Quelques fonctions dont vous avez besoin éventuellement : Math.pow(2,n) // 2 ^ n

x=(int)(Math.random()*m) // générer un entier au hazard entre 0 et m-1

Integer.parseInt(mot,2); // convertir un entier binaire sous forme de chaîne de caractères en entier décimal

Partie 2 : Casier pour ranger des objets … généricité, Exception, thread, …..

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.util.ArrayList;

public class Casier {

private ArrayList contenu;

(2)

public Casier(int taille) {

contenu = new ArrayList(taille);

for (int i = 0; i < taille ; ++i) contenu.add(null);

}

public Object get(int position) { return contenu.get(position-1);

}

public void ranger(int position, Object element) { if (this.estVide(position))

contenu.set(position-1, element);

}

public Object retirer(int position) {

return contenu.set(position-1, null); // set renvoie l'élément précédemment stoké }

public boolean estVide(int position) { return (contenu.get(position-1) == null);

}

public void sauvegarder(String nomFichier) throws IOException { File fichierPersistant = new File(nomFichier);

if ((fichierPersistant.exists() && fichierPersistant.isFile() && fichierPersistant.canWrite())

|| fichierPersistant.createNewFile()) {

ObjectOutputStream flotEcriture = new ObjectOutputStream(new

FileOutputStream(fichierPersistant));

flotEcriture.writeObject(this);

flotEcriture.close();

} else

throw new IOException ("impossible de Sauvegarder");

}

public void restaurer(String nomFichier) throws IOException { File fichierPersistant = new File(nomFichier);

try {

if (fichierPersistant.exists() && fichierPersistant.isFile() && fichierPersistant.canRead()) {

ObjectInputStream flotLecture = new ObjectInputStream(new

FileInputStream(fichierPersistant));

Casier sauvegarde = (Casier)flotLecture.readObject();

this.contenu = sauvegarde.contenu ; flotLecture.close();

} else

throw new IOException ("impossible de Restaurer");

} catch (ClassNotFoundException cnfe) {

throw new IOException ("impossible de Restaurer");

} }

public String toString() {

StringBuffer resultat = new StringBuffer();

for (int i = 1; i <= this.contenu.size() ; ++i) { resultat.append("case["+i+";]=");

if (! this.estVide(i))

resultat.append(this.get(i));

resultat.append("\n");

}

return resultat.toString();

} }

Et l'interface graphique la classe ManipulationCasierDeMot : Ci-contre une exécution

import java.awt.event.ActionEvent;

(3)

import java.awt.event.ActionListener;

import java.io.IOException;

import javax.swing.Box;

import javax.swing.BoxLayout;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JSpinner;

import javax.swing.JTextArea;

import javax.swing.JTextField;

import javax.swing.SpinnerNumberModel;

public class ManipulationCasierDeMot extends JFrame { private final int TAILLE = 9;

private final String SAUVEGARDE = ".monEnsemble";

private Casier monCasier;

private JTextField elementMot;

private JSpinner numeroCase;

private JTextArea resultat;

private JLabel etatOperation;

public ManipulationCasierDeMot() { super();

monCasier = new Casier(TAILLE);

Box boiteTout = new Box(BoxLayout.Y_AXIS);

Box boiteOperation = new Box(BoxLayout.X_AXIS);

JButton boutonRanger = new JButton("Ranger");

boiteOperation.add(boutonRanger);

boutonRanger.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { etatOperation.setText(" ");

String sansBlanc = elementMot.getText().trim();

if (sansBlanc.length()>0) {

monCasier.ranger((int)numeroCase.getValue(), sansBlanc);

resultat.setText(monCasier.toString());

} else

etatOperation.setText("erreur mot vide ");

elementMot.setText("");

} });

JButton boutonRetirer = new JButton("Enlever");

boiteOperation.add(boutonRetirer);

boutonRetirer.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

etatOperation.setText(" ");

String element = monCasier.retirer((int)numeroCase.getValue());

elementMot.setText((element == null)?"":element);

resultat.setText(monCasier.toString());

} });

boiteTout.add(boiteOperation);

Box boiteParametres = new Box(BoxLayout.X_AXIS);

boiteParametres.add(new JLabel("num : "));

numeroCase = new JSpinner(new SpinnerNumberModel(1,1,9,1));

boiteParametres.add(numeroCase);

boiteParametres.add(new JLabel(" élément : "));

elementMot = new JTextField(" ");

boiteParametres.add(elementMot);

boiteTout.add(boiteParametres);

resultat = new JTextArea(TAILLE, 10);

resultat.setEditable(false);

resultat.setText(monCasier.toString());

boiteTout.add(resultat);

(4)

Box boiteSauverRestaurer = new Box(BoxLayout.X_AXIS);

JButton boutonSauver = new JButton("Sauvegarder");

boutonSauver.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { etatOperation.setText(" ");

Thread sauver = new Thread(new Sauvegarder(SAUVEGARDE));

sauver.start();

} });

boiteSauverRestaurer.add(boutonSauver);

JButton boutonRestaurer = new JButton("Restaurer");

boutonRestaurer.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

etatOperation.setText(" ");

Thread restaurer = new Thread(new Restaurer(SAUVEGARDE));

restaurer.start();

try {

restaurer.join();

} catch (InterruptedException e1) {

etatOperation.setText("impossible de Restaurer");

} } });

boiteSauverRestaurer.add(boutonRestaurer);

boiteTout.add(boiteSauverRestaurer);

etatOperation = new JLabel(" ");

boiteTout.add(etatOperation);

this.setContentPane(boiteTout);

this.setDefaultCloseOperation(getDefaultCloseOperation());

this.pack();

this.setVisible(true);

}

class Sauvegarder implements Runnable { private String nomFichier;

private boolean etat ;

public Sauvegarder(String nomFichier) { this.nomFichier = nomFichier;

}

public void run() { try {

monCasier.sauvegarder(nomFichier);

etatOperation.setText("sauvegarde réussie");

} catch (IOException ioe) {

etatOperation.setText("erreur de sauvegarde ");

} }

}

class Restaurer implements Runnable { private String nomFichier;

private boolean etat ;

public Restaurer(String nomFichier) { this.nomFichier = nomFichier;

}

public void run() { try {

monCasier.restaurer(nomFichier);

resultat.setText(monCasier.toString());

etatOperation.setText("restauration réussie");

} catch (IOException ioe) {

etatOperation.setText("erreur de restauration ");

} }

}

(5)

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() {

new ManipulationCasierDeMot();

} });

} }

Les questions sont indépendantes !

Question A :

La programmation événementielle des boutons "Sauvegarder" et "Restaurer" tient compte que les lectures et écritures dans un fichier sont des opérations longues, et que les opérations longues ne doivent pas monopoliser le thread graphique.

La programmation du bouton "Sauvegarder" lance donc un thread qui réalise l'écriture dans un fichier.

Malheureusement l'utilisateur peut continuer de manipuler le casier pendant ce même temps.

Il serait souhaitable de faire une copie qui sera sauvegardée. Le code serait donc :

class Sauvegarder implements Runnable { private String nomFichier;

private boolean etat ; private Casier copie;

public Sauvegarder(String nomFichier) { this.nomFichier = nomFichier;

try {

this.copie = (Casier)monCasier.clone() ; } catch (CloneNotSupportedException cnse) {

etatOperation.setText("erreur de sauvegarde ");

} }

public void run() { try {

copie.sauvegarder(nomFichier);

etatOperation.setText("sauvegarde réussie");

} catch (IOException ioe) {

etatOperation.setText("erreur de sauvegarde ");

} }

}

Que faut-il ajouter et/ou modifier dans la classe Casier ?

Question B :

Attention à ce que les opérations "graphiques" soient bien traitées par le thread graphique.

En regardant précisément le code du bouton "Restaurer", les composants graphiques "etatOperation" et

"resultat" sont manipulés par un thread autre que l'event-dispatcher.

Proposez une solution programmée.

Question C :

J'essaye le bouton Sauvegarder …. Catastrophe !

java.io.NotSerializableException: Casier

at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) at Casier.sauvegarder(Casier.java:38)

at ManipulationCasierDeMot$Sauvegarder.go(ManipulationCasierDeMot.java:110) at ManipulationCasierDeMot$3.actionPerformed(ManipulationCasierDeMot.java:77) ...

(6)

Que faut-il ajouter et à quel endroit pour corriger cela ?

Question D :

Nous voudrions que le casier ne comporte que des éléments de même type.

Que faut-il modifier dans la classe Clavier (sans les ajouts éventuels des questions A, B et C) pour que cette classe soit générique ?

Ne donnez que les modifications, ne re-écrivez pas toute la classe.

Question E :

Il faudrait améliorer les traitements des situations d'exceptions de la classe Casier.

Comment re-écrire la méthode ranger( ) afin qu'elle propage des IndexOutOfBoundsException si la position est hors des cases ou des IllegalArgumentException si la présente case est déjà occupée ?

Proposez, en conséquence, une re-écriture de la méthode actionPerformed( ) du bouton "Ranger" dans la classe

ManipulationCasierDeMot.

Références

Documents relatifs

[r]

Reporter ces valeurs dans la première ligne du tableau de signe ci-dessous.. x

Reporter ces valeurs dans la première ligne du tableau de signe ci-dessous.. x

Die Programme P18 bis P22 sind Pulsschlag-Kontroll-Programme, wobei P22 für das Programm zum individuell angestrebten Pulsschlag steht. Training mit Ihrem individuellen Zielpuls.

So you need to provide a Words list file that is preloaded with all the passwords you suspect.. For example, if you suspect that the password would be any one of the words

Cette application est composée d’une classe Dictionnaire.java comme modèle, une classe VueGraphik comme vue et une classe ContrôleurGraphik comme contrôleur.. Nous donnons le code

Améliorez aussi la classe Joueur de test LotoAPlusieurs pour que le tirage d'un jeton et sa remise dans le sac se fasse en exclusion mutuelle des autres joueurs : si le joueur A

Écrire la partie attente des résultats de telle sorte que votre solution soit « thread-safe » et sans