diff --git a/.gitignore b/src/.gitignore similarity index 100% rename from .gitignore rename to src/.gitignore diff --git a/src/controleur/ControleurPartie.java b/src/controleur/ControleurPartie.java index a876d2f..80598f2 100644 --- a/src/controleur/ControleurPartie.java +++ b/src/controleur/ControleurPartie.java @@ -27,15 +27,17 @@ public class ControleurPartie { System.out.println("===============================\n"); - vue.afficherMessage(TypeMessage.SYSTEME,"Mode de jeu : " + modeDeJeu); - vue.afficherMessage(TypeMessage.SYSTEME,"Joueurs : " + partie.getJoueurBlanc().getNom() + " (Blancs) vs " + partie.getJoueurNoir().getNom() + " (Noirs)"); - vue.afficherMessage(TypeMessage.SYSTEME,"Les pions Noirs sont en bas. Les pions Blancs sont en haut. \n"); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Mode de jeu : " + modeDeJeu); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Joueurs : " + partie.getJoueurBlanc().getNom() + " (Blancs) vs " + partie.getJoueurNoir().getNom() + " (Noirs)"); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Les pions Noirs sont en bas. Les pions Blancs sont en haut. \n"); - vue.afficherMessage(TypeMessage.SYSTEME,"------- La Partie commence ! -------"); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"------- La Partie commence ! -------"); vue.afficherPlateau(partie.getPlateau()); //System.out.print("\n"); - vue.afficherMessage(TypeMessage.SYSTEME,"C'est au tour de " + partie.getJoueurActif().getNom() + " de jouer."); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"C'est au tour de " + partie.getJoueurActif().getNom() + " de jouer."); boucleDeJeu(); + vue.setTour(partie.getJoueurActif().getNom()); + vue.setScore(partie.getScore()); } public void boucleDeJeu(){ @@ -49,20 +51,21 @@ public class ControleurPartie { vue.afficherPlateau(partie.getPlateau()); if(dernierCoup != null) { - vue.afficherMessage(TypeMessage.SYSTEME,"Dernier coup : " + joueurPrecedent.getNom() + " a joué " + dernierCoup); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Dernier coup : " + joueurPrecedent.getNom() + " a joué " + dernierCoup); } - vue.afficherMessage(TypeMessage.SYSTEME,"\nC'est au tour de " + partie.getJoueurActif().getNom() + " de jouer."); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"\nC'est au tour de " + partie.getJoueurActif().getNom() + " de jouer."); vue.setTour(partie.getJoueurActif().getNom()); + vue.setScore(partie.getScore()); } catch (IllegalArgumentException e) { - vue.afficherMessage(TypeMessage.SYSTEME,"> Erreur : " + e.getMessage()); + vue.afficherMessage(TypeMessage.SYSTEMEROUGE,"> Erreur : " + e.getMessage()); } } - vue.afficherMessage(TypeMessage.SYSTEME,"La partie est terminée !"); - vue.afficherMessage(TypeMessage.SYSTEME,"Si vous souhaitez rejouer, relancez le programme."); - vue.afficherMessage(TypeMessage.SYSTEME,"Si vous souhaitez voir l'historique des coups taper 1. Si vous souhaitez voir les captures taper 2."); - vue.afficherMessage(TypeMessage.SYSTEME,"Merci d'avoir joué !"); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"La partie est terminée !"); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Si vous souhaitez rejouer, relancez le programme."); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Si vous souhaitez voir l'historique des coups taper 1. Si vous souhaitez voir les captures taper 2."); + vue.afficherMessage(TypeMessage.SYSTEMEBLEU,"Merci d'avoir joué !"); } } diff --git a/src/modele/Coup.java b/src/modele/Coup.java index 3fb7f57..fe8ab60 100644 --- a/src/modele/Coup.java +++ b/src/modele/Coup.java @@ -1,8 +1,12 @@ package modele; import java.awt.Point; +import java.io.*; + + +public class Coup implements Serializable { + private static final long serialVersionUID = 1L; -public class Coup { private int ligneDepart; private int colDepart; private int ligneArrivee; diff --git a/src/modele/Partie.java b/src/modele/Partie.java index 4807579..e4baaf1 100644 --- a/src/modele/Partie.java +++ b/src/modele/Partie.java @@ -102,6 +102,10 @@ public class Partie{ nombreCoups++; } + public String getScore() { + return "Blancs : " + listeCapturesBlancs.size() + " - Noirs : " + listeCapturesNoires.size(); + } + public Joueur getJoueurActif() { return joueurActif; } diff --git a/src/out/controleur/ControleurPartie.class b/src/out/controleur/ControleurPartie.class index 71d4547..7f1d115 100644 Binary files a/src/out/controleur/ControleurPartie.class and b/src/out/controleur/ControleurPartie.class differ diff --git a/src/out/modele/Partie.class b/src/out/modele/Partie.class index e29d440..75b17d5 100644 Binary files a/src/out/modele/Partie.class and b/src/out/modele/Partie.class differ diff --git a/src/out/reseau/TypeMessage.class b/src/out/reseau/TypeMessage.class index d0e8e72..61d5edb 100644 Binary files a/src/out/reseau/TypeMessage.class and b/src/out/reseau/TypeMessage.class differ diff --git a/src/out/vue/ButtonEnvoyerMessageListener.class b/src/out/vue/ButtonEnvoyerMessageListener.class new file mode 100644 index 0000000..0ebc8b1 Binary files /dev/null and b/src/out/vue/ButtonEnvoyerMessageListener.class differ diff --git a/src/out/vue/ToucheEntrerEnvoyerMessageListener.class b/src/out/vue/ToucheEntrerEnvoyerMessageListener.class new file mode 100644 index 0000000..456ff2a Binary files /dev/null and b/src/out/vue/ToucheEntrerEnvoyerMessageListener.class differ diff --git a/src/out/vue/VueGraphiqueSwing$1.class b/src/out/vue/VueGraphiqueSwing$1.class index 468f66b..00e0feb 100644 Binary files a/src/out/vue/VueGraphiqueSwing$1.class and b/src/out/vue/VueGraphiqueSwing$1.class differ diff --git a/src/out/vue/VueGraphiqueSwing.class b/src/out/vue/VueGraphiqueSwing.class index 72bae30..c99eaa6 100644 Binary files a/src/out/vue/VueGraphiqueSwing.class and b/src/out/vue/VueGraphiqueSwing.class differ diff --git a/src/reseau/MessageJeu.java b/src/reseau/MessageJeu.java index bd51652..4b45d56 100644 --- a/src/reseau/MessageJeu.java +++ b/src/reseau/MessageJeu.java @@ -1,5 +1,42 @@ package reseau; -public class MessageJeu { +import java.io.*; +import modele.Coup; + +public class MessageJeu implements Serializable { + private static final long serialVersionUID = 1L; + + private final TypeMessage type; // CHAT, COUP, SYSTEME, DEMANDE_DE_PARTIE, FIN_DE_PARTIE + private final String auteur; // MOI adversaire ou système + private final String contenu; // Pour les messages texte Chat/système + private final Coup coup; //Pour les mouvements sinon null + + public MessageJeu(TypeMessage type, String auteur, String contenu, Coup coup) { + this.type = type; + this.auteur = auteur; + this.contenu = contenu; + this.coup = coup; + } + + public TypeMessage getType() { + return type; + } + + public String getContenu() { + return contenu; + } + + public String getAuteur() { + return auteur; + } + + public Coup getCoup() { + return coup; + } + + @Override + public String toString() { + return "[" + type + "] " + auteur + " : " + contenu + (coup != null ? " (Coup: " + coup + ")" : ""); + } } diff --git a/src/reseau/Serveur.java b/src/reseau/Serveur.java index a9f937f..c32ddbe 100644 --- a/src/reseau/Serveur.java +++ b/src/reseau/Serveur.java @@ -1,5 +1,51 @@ package reseau; +import java.io.*; +import java.net.*; + +import controleur.ControleurReseau; + + public class Serveur { + private final int port; + private ObjectInputStream input; // flux d'entrée qui vient du client + private ObjectOutputStream output; // flux de sortie qui va vers le client + private ControleurReseau controleur; + + public Serveur(int port){ + this.port = port; + } + + public void setControleur(ControleurReseau controleur) { + this.controleur = controleur; + } + + public void demarrer() throws IOException{ + ServerSocket serveurSocket = new ServerSocket(port); + System.out.println("Serveur démarré sur le port " + port); + + // Accepter une connexion seule client + Socket clientSocket = serveurSocket.accept(); + System.out.println("Client connecté : " + clientSocket.getInetAddress()); + + // Initialiser les flux de communication + output = new ObjectOutputStream(clientSocket.getOutputStream()); + input = new ObjectInputStream(clientSocket.getInputStream()); + + // Démarrer un thread pour écouter les messages entrants + new Thread(()-> { + try { + while(true) { + MessageJeu message = (MessageJeu) input.readObject(); + traiterMessage(message); + } + } catch (Exception e) { + if(controleur != null) { + controleur.onSyteme("Client déconnecté."); + } + } + }) + + } } diff --git a/src/reseau/TypeMessage.java b/src/reseau/TypeMessage.java index 1529f9b..3eaf8a8 100644 --- a/src/reseau/TypeMessage.java +++ b/src/reseau/TypeMessage.java @@ -5,7 +5,8 @@ public enum TypeMessage { MOUVEMENT, // Transmission d'un coup FIN_DE_PARTIE, // Signal de fin - SYSTEME, // Message système (erreur, info serveur, etc.) + SYSTEMEBLEU, // Message système ( info serveur, etc.) + SYSTEMEROUGE, // Message système ( info serveur, etc.) en rouge CHAT // Message chat entre joueurs } \ No newline at end of file diff --git a/src/vue/ButtonEnvoyerMessageListener.java b/src/vue/ButtonEnvoyerMessageListener.java new file mode 100644 index 0000000..64ac1ae --- /dev/null +++ b/src/vue/ButtonEnvoyerMessageListener.java @@ -0,0 +1,23 @@ +package vue; + +import java.awt.event.*; +import javax.swing.*; + +public class ButtonEnvoyerMessageListener implements ActionListener { + private JTextField champ; + private VueGraphiqueSwing vue; + + public ButtonEnvoyerMessageListener(JTextField champ, VueGraphiqueSwing vue) { + this.champ = champ; + this.vue = vue; + } + + @Override + public void actionPerformed(ActionEvent e) { + String msg = champ.getText().trim(); + if (!msg.isEmpty()) { + vue.ajouterMessageChat("Moi", msg); + champ.setText(""); // Efface le champ après envoi + } + } +} diff --git a/src/vue/ToucheEntrerEnvoyerMessageListener.java b/src/vue/ToucheEntrerEnvoyerMessageListener.java new file mode 100644 index 0000000..07460a0 --- /dev/null +++ b/src/vue/ToucheEntrerEnvoyerMessageListener.java @@ -0,0 +1,31 @@ +package vue; + +import java.awt.event.*; +import javax.swing.*; + +public class ToucheEntrerEnvoyerMessageListener implements KeyListener { + private JTextField champ; + private VueGraphiqueSwing vue; + + public ToucheEntrerEnvoyerMessageListener(JTextField champ, VueGraphiqueSwing vue) { + this.champ = champ; + this.vue = vue; + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + String msg = champ.getText().trim(); + if (!msg.isEmpty()) { + vue.ajouterMessageChat("Moi", msg); + champ.setText(""); // Efface le champ après envoi + } + } + } + + @Override + public void keyReleased(KeyEvent e) {} + + @Override + public void keyTyped(KeyEvent e) {} +} diff --git a/src/vue/VueGraphiqueSwing.java b/src/vue/VueGraphiqueSwing.java index 9d54b51..b2e69c1 100644 --- a/src/vue/VueGraphiqueSwing.java +++ b/src/vue/VueGraphiqueSwing.java @@ -22,6 +22,7 @@ public class VueGraphiqueSwing implements Vue { private final JLabel lblScore = new JLabel("Score : "); private final JPanel panelSysteme = new JPanel(); + private JScrollPane scrollMessages; public VueGraphiqueSwing(Partie partie) { fen = new JFrame("CHESS GAME"); @@ -54,14 +55,30 @@ public class VueGraphiqueSwing implements Vue { scrollSysteme.setBorder(BorderFactory.createTitledBorder("Système")); droite.add(scrollSysteme, BorderLayout.CENTER); - // === Colonne gauche (messages serveur) === + // Colonne gauche (messages serveur + input) panelMessages.setLayout(new BoxLayout(panelMessages, BoxLayout.Y_AXIS)); panelMessages.setPreferredSize(new Dimension(200, 0)); panelMessages.setMinimumSize(new Dimension(200, 0)); - JScrollPane scrollMessages = new JScrollPane(panelMessages); + scrollMessages = new JScrollPane(panelMessages); scrollMessages.setBorder(BorderFactory.createTitledBorder("Messages (serveur)")); - // === JSplitPane centre (plateau + droite) === + // Champ de saisie et bouton + JTextField champMessage = new JTextField(); + JButton btnEnvoyer = new JButton("Envoyer"); + btnEnvoyer.addActionListener(new ButtonEnvoyerMessageListener(champMessage, this)); + champMessage.addKeyListener(new ToucheEntrerEnvoyerMessageListener(champMessage, this)); + + // Panneau bas (saisie + bouton) + JPanel basGauche = new JPanel(new BorderLayout(5, 0)); + basGauche.add(champMessage, BorderLayout.CENTER); + basGauche.add(btnEnvoyer, BorderLayout.EAST); + + // Panneau global gauche + JPanel gauche = new JPanel(new BorderLayout()); + gauche.add(scrollMessages, BorderLayout.CENTER); + gauche.add(basGauche, BorderLayout.SOUTH); + + // JSplitPane centre (plateau + droite) JSplitPane splitCentre = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, plateauUI, @@ -71,10 +88,10 @@ public class VueGraphiqueSwing implements Vue { splitCentre.setResizeWeight(0.7); splitCentre.setOneTouchExpandable(true); - // === JSplitPane global (gauche + centre) === + // JSplitPane global (gauche + centre) JSplitPane splitGlobal = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, - scrollMessages, + gauche, splitCentre ); splitGlobal.setDividerLocation(200); @@ -89,57 +106,96 @@ public class VueGraphiqueSwing implements Vue { fen.setVisible(true); } - private JPanel createMessageBlock(String text, Color bg, Color fg) { - JLabel lbl = new JLabel(text); - lbl.setForeground(fg); + private JPanel createMessageBlock(String auteur, String text) { + JLabel lbl = new JLabel(auteur + " : " + text); JPanel block = new JPanel(new BorderLayout()); block.add(lbl, BorderLayout.CENTER); - // Style + // Couleur selon auteur + Color bg, fg, border; + switch (auteur.toLowerCase()) { + case "moi" -> { + bg = new Color(200, 255, 200); // vert clair + fg = Color.BLACK; + border = Color.GREEN.darker(); + } + case "serveurbleu" -> { + bg = new Color(220, 235, 255); // bleu clair + fg = Color.BLUE.darker(); + border = Color.BLUE; + } + case "serveurrouge" -> { + bg = new Color(255, 220, 220); // rouge clair + fg = Color.RED.darker(); + border = Color.RED; + } + default -> { // adversaire + bg = new Color(255, 220, 220); // rouge clair + fg = Color.RED.darker(); + border = Color.RED; + } + } + block.setBackground(bg); + lbl.setForeground(fg); block.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createEmptyBorder(5, 10, 5, 10), // marges internes - BorderFactory.createLineBorder(Color.GRAY, 1) // bordure + BorderFactory.createLineBorder(border, 1), + BorderFactory.createEmptyBorder(5, 10, 5, 10) )); - // Taille fixe : largeur dynamique, hauteur compacte - block.setPreferredSize(new Dimension(0, 35)); // hauteur 35 px - block.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); // largeur étirable, hauteur fixée + // Taille compacte + block.setPreferredSize(new Dimension(0, 35)); + block.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); block.setMinimumSize(new Dimension(100, 35)); return block; } + // Ajouter message serveur (colonne gauche) - public void ajouterMessageChat(String message) { - SwingUtilities.invokeLater(() -> { // assure que c'est dans le thread Swing - JPanel block = createMessageBlock(message, Color.WHITE, Color.BLACK); + public void ajouterMessageChat(String auteur, String message) { + SwingUtilities.invokeLater(() -> { + JPanel block = createMessageBlock(auteur, message); panelMessages.add(block); - panelSysteme.add(Box.createVerticalStrut(8)); + panelMessages.add(Box.createVerticalStrut(15)); panelMessages.revalidate(); panelMessages.repaint(); + + // Déplacer la scrollbar après que Swing ait fini la mise en page + SwingUtilities.invokeLater(() -> { + JScrollBar verticalBar = scrollMessages.getVerticalScrollBar(); + verticalBar.setValue(verticalBar.getMaximum()); + }); }); } + // Ajouter message système (colonne droite bas) - public void ajouterMessageSysteme(String message) { + public void ajouterMessageSysteme(String auteur, String message) { SwingUtilities.invokeLater(() -> { - JPanel block = createMessageBlock(message, new Color(255,220,220), Color.RED); + JPanel block = createMessageBlock(auteur, message); panelSysteme.add(block); panelSysteme.add(Box.createVerticalStrut(15)); panelSysteme.revalidate(); panelSysteme.repaint(); }); + + // Déplacer la scrollbar après que Swing ait fini la mise en page + SwingUtilities.invokeLater(() -> { + JScrollBar verticalBar = scrollMessages.getVerticalScrollBar(); + verticalBar.setValue(verticalBar.getMaximum()); + }); } // API de la Vue @Override public void afficherMessage(TypeMessage type, String message) { switch (type) { - case CHAT : ajouterMessageChat(message); - case SYSTEME : ajouterMessageSysteme(message); + case CHAT : ajouterMessageChat("", message); break; + case SYSTEMEBLEU : ajouterMessageSysteme("serveurBleu", message); break; + case SYSTEMEROUGE : ajouterMessageSysteme("serveurRouge", message); break; default : System.out.println("[INFO] " + message); } }