Morpion - interface graphique - jpanel - dessin

Description

Jeu de morpion contre l'ordinateur.
Permet de travailler sur l'interface graphique, les panneaux, les boutons, les clicks de souris,
le dessin ...

Source / Exemple :


/*******************************************************************	
	Classes Java permettant de jouer au Morpion contre l'ordinateur
	Le joueur peut rentrer son nom et choisir son symbole.

                                                                                                                                          • /
import javax.swing.*; // Librairie graphique import java.awt.*; // Composants Java import java.awt.event.*; // Permet d'utiliser les événements liés aux composants import java.util.*; // Utilitaires, ici pour la génération de nombres aléatoires /******************************************************************** Classe MorpionFrame permettant d'instancier un objet JFrame (Fenetre) contenant 9 JPanel (panneaux) représentant les cases du jeu ainsi qu'un bouton permettant de commencer la partie. Les objets de type Paneau sont des dérivés de la classe JPanel. La classe Paneau est commentée plus bas. Les objets de type Partie représentent la partie en cours. La classe Partie est commentée plus bas.
                                                                                                                                          • /
class MorpionFrame extends JFrame implements ActionListener { private Paneau pan0,pan1,pan2,pan3,pan4,pan5,pan6,pan7,pan8; private Paneau pans[] = { pan0,pan1,pan2,pan3,pan4,pan5,pan6,pan7,pan8 }; private Partie part; private JPanel haut, bas; private JButton but; private GridLayout grid; // Constructeur de la classe Morpion public MorpionFrame() { setTitle("Morpion"); Container cont = getContentPane(); // Le tableau des Paneau est transmis au constructeur de Partie part = new Partie(pans); // Création de 2 JPanel pour la mise en forme de la fenetre haut = new JPanel(); cont.add(haut); bas = new JPanel(); cont.add(bas,"South"); // Le gestionnaire de mise en forme du Panel haut est redéfini // en grille de 3 lignes, 3 colonnes avec 2 pixels entre chaques haut.setLayout(new GridLayout(3,3,2,2)); // Création des 9 Paneau et ajout au Panel haut for (int i=0 ; i<9 ; i++) { pans[i] = new Paneau(part,i); haut.add(pans[i]); } // Définition du bouton, ajout au Panel bas but = new JButton("Commencer"); bas.add(but); // Ajout d'un ActionListener (écouteur d'action) sur le bouton // Cela va permettre d'intercepter le click par le biais de la // méthode actionPerformed (nom de méthode déja défini et à respecter) but.addActionListener(this); } // Methode qui intercepte toutes les actions se déroulant dans la classe // Reçoit l'évenement déclencheur en argument public void actionPerformed(ActionEvent e) { // Test sur la source de l'évènement // Ici le test aurait pu etre supprimé etant donné qu'il n'y à // q'un seul bouton dans ma classe if (e.getSource() == but) { // Création d'une boite de dialogue de type bDial dérivée de JDial // Le constructeur attend comme argument une fenetre et une partie bDial dial = new bDial(this,part); dial.setSize(200,150); // Recupere la taille de l'écran et positionne lla bDial au milieu Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); dial.setLocation((screenSize.width-dial.getWidth())/2,(screenSize.height-dial.getHeight())/2); dial.setVisible(true); // Lance la partie part.commencer(); } } } /************************************************************************** Classe bDial permettant d'instancier un objet JDialog personnalisé pour demander le nom du joueur et lui donner le choix du symbole. Elle contient des labels, un champ texte, une combo (liste déroulante), un bouton et une référence à la partie en cours.
                                                                                                                                                    • /
class bDial extends JDialog implements ActionListener { private JButton butOk; private JLabel lNom,lSymb,lRegl; private JTextField fNom; private JComboBox bSymb; private Partie _part; // Constructeur de bDial // Argument 1 : La fenetre à laquelle la bDial appartient // Argument 2 : La partie en cours public bDial(JFrame prop,Partie part) { // Appel du constructeur de la classe de base (JDialog) super (prop, "Informations Joueur", true); _part = part; butOk = new JButton("Ok"); lNom = new JLabel(" Votre nom :"); fNom = new JTextField(10); fNom.setText("Moi"); lSymb = new JLabel(" Symbole :"); lRegl = new JLabel(" Le rond commence la partie !"); String tSymb[] = { "Croix", "Rond" }; bSymb = new JComboBox(tSymb); bSymb.setSelectedIndex(1); JPanel haut = new JPanel(); JPanel bas = new JPanel(); JPanel mil = new JPanel(); Container c = getContentPane(); c.add(haut,"North"); c.add(mil); c.add(bas,"South"); haut.setLayout(new GridLayout(2,2,5,5)); haut.add(lNom); haut.add(fNom); haut.add(lSymb); haut.add(bSymb); mil.add(lRegl); bas.add(butOk); butOk.addActionListener(this); } public void actionPerformed(ActionEvent e) { // Création du joueur dans la partie _part.createJoueurs((int)bSymb.getSelectedIndex(), fNom.getText()); setVisible(false); // Destruction de l'objet bDial dispose(); } } /*********************************************************** Classe Joueur permettant de créer des joueurs. Ses deux membres sont le nom et le symbole du joueur.
                                                                                                                        • /
class Joueur { private int _symb; private String _nom; // Constructeur de Joueur // Reçoit le nom et le symbole et les affectent public Joueur(int symb, String nom) { _symb = symb; _nom = nom; } // Méthode qui renvoit le symbole public int getSymb() { return _symb; } // Méthode qui renvoit le nom public String getNom() { return _nom; } } /***************************************************************** Classe Partie permettant de créer une partie Elle contient : - 4 constantes permettant de rendre le code plus lisible !! - un booleen reflétant l'état de la partie (en cours ou non) - un tableau d'entiers représentant la zone de jeu et l'état des cases (rond, croix, rien) -> tab. - un autre tableau qui contient les différentes combinaisons gagnantes -> sol - 1 entier permettant de stocker l'endroit ou l'ordinateur doit jouer -> strat. - 2 Joueurs. - Une référence au tableau de Paneau de MorpionFrame
                                                                                                                                    • /
class Partie { static public final int CROIX = 0; static public final int ROND = 1; static public final int RIEN = 2; static public final int NON = 10; private boolean isRunning = false; private int tab[] = { RIEN,RIEN,RIEN,RIEN,RIEN,RIEN,RIEN,RIEN,RIEN }; private int sol[][] = { {0,1,2}, {3,4,5}, {6,7,8}, {0,3,6}, {1,4,7}, {2,5,8}, {0,4,8}, {2,4,6} }; private int strat = NON; private Joueur j1,j2; private Paneau pans[]; // Constructeur de Partie // Reçoit la référence au tableau de Paneau et l'affecte public Partie(Paneau t[]) { pans = t; } // Création des Joueurs // Reçoit le nom et le symbole choisi par l'utilisateur dans la bDial public void createJoueurs(int symb, String nom) { j1 = new Joueur(symb,nom); if (symb == CROIX) { j2 = new Joueur(ROND,"L'Ordinateur"); jeuOrdi(); } else j2 = new Joueur(CROIX,"L'Ordinateur"); } // Méthode qui renvoit le contenu d'une case donnée de tab public int getCase(int _case) { return tab[_case]; } // Méthode qui affecte le contenu d'une case donnée de tab public void setCase(int _case, int symb) { tab[_case] = symb; } // Méthode qui initialise la partie public void commencer() { isRunning = true; } // Méthode qui fait jouer l'ordinateur // Teste si l'ordinateur peut gagner sur ce coup // Si oui joue ou il faut grace a ouJouer() // Si non, teste si l'ordinateur peut perdre au prochain coup // Si oui joue ou il faut pour l'empécher grace à ouJouer() // Si non teste si il peut essayer de mettre en place une combinaison gagnante // Si oui il le fait grace a isStrat() // Si non joue aléatoirement public void jeuOrdi() { int jouEn; jouEn = ouJouer(j2.getSymb()); if (jouEn == NON) { jouEn = ouJouer(j1.getSymb()); if (jouEn == NON) { isStrat(); if (strat == NON) { Random alea = new Random(); // Génère un nombre entre 0 et 8 jouEn = alea.nextInt(9); // Recommence si la case est prise while ( tab[jouEn] != RIEN ) jouEn = alea.nextInt(9); } else jouEn = strat; } } // Met tab à jour tab[jouEn] = j2.getSymb(); // Dessine sur le Paneau correspondant pans[jouEn].setSymbo(j2.getSymb()); pans[jouEn].repaint(); // Appel de la méthode qui interroge les règles // pour voir si la partie est finie // Lui transmet le joueur intRegl(j2); } // Méthode qui interroge les règles en transmettant // le dernier symbole joué // Reçoit un joueur en argument // Si un joueur à gagné ou qu'il y a match nul : propose de rejouer public void intRegl(Joueur j) { int result = regles(j.getSymb()); if (result == 1) { JOptionPane.showMessageDialog(null,j.getNom() + " a Gagné !"); int rep = JOptionPane.showConfirmDialog(null,"Voulez vous rejouer ?","Partie finie",JOptionPane.YES_NO_OPTION) ; propRej(rep); } else if ( ( j.getNom() != "L'Ordinateur" ) && (result != RIEN) ) jeuOrdi(); if (result == RIEN) { int rep = JOptionPane.showConfirmDialog(null,"Voulez vous rejouer ?","Partie finie",JOptionPane.YES_NO_OPTION) ; propRej(rep); } } // Méthode qui gère la réponse à la proposition de rejouer // Attend la réponse comme argument // Si oui -> remet tout à zéro // Si non -> quitte l'application public void propRej(int rep) { if (rep == 0) { for (int i = 0 ; i < 9 ; i++) { pans[i].setSymbo(RIEN); pans[i].setDejDess(false); pans[i].repaint(); tab[i] = RIEN; } if (j2.getSymb() == ROND) jeuOrdi(); } else System.exit(0); } // Méthode qui est appelée quand l'utilisateur clique sur un Paneau // Reçoit une référence au Paneau en argument public void jeu(Paneau p) { // Teste si le Paneau est déja dessiné ou non if (p.getDejDess() == false) { p.setDejDess(true); // Dessine sur le Paneau et met tab à jour p.setSymbo(j1.getSymb()); tab[p.getIndice()] = j1.getSymb(); p.repaint(); // Appelle l'interrogation des règles pour l'utilisateur intRegl(j1); } } // Méthode qui renvoit l'état de la partie public boolean getIsRunning() { return isRunning; } // Méthode qui détermine si l'ordinateur peut perdre ou gagner au prochain coup // Parcours le tableau des combinaisons gagnantes et regarde si // le symbole reçu peut en faire une ou au prochain coup // si oui -> affecte le numéro de la case d'ou vient le danger/la solution à jouer public int ouJouer(int symb) { int cases = 0,c1,c2,c3; int jouer = NON; while ( (jouer == NON) && (cases < 8) ) { for (cases = 0 ; cases < 8 ; cases++) { c1 = tab[sol[cases][0]]; c2 = tab[sol[cases][1]]; c3 = tab[sol[cases][2]]; if ( (c1 == symb) && ( (c2 == c1) && (c3 == RIEN) ) ) jouer = sol[cases][2]; if ( (c1 == symb) && ( (c3 == c1) && (c2 == RIEN) ) ) jouer = sol[cases][1]; if ( (c2 == symb) && ( (c2 == c3) && (c1 == RIEN) ) ) jouer = sol[cases][0]; } } return jouer; } // Méthode qui détermine si l'ordinateur peut gagner dans 2 coups // Parcours le tableau des combinaisons gagnantes et regarde si // il peut en faire une dans 2 coups // si oui -> affecte le numéro d'une des cases gagnantes à strat public void isStrat() { int cases = 0,c1,c2,c3; strat = NON; while ( (strat == NON) && (cases < 8) ) { for (cases = 0 ; cases < 8 ; cases++) { c1 = tab[sol[cases][0]]; c2 = tab[sol[cases][1]]; c3 = tab[sol[cases][2]]; if ( (c1 == j2.getSymb()) && ( (c2 == c3) && (c3 == RIEN) ) ) strat = sol[cases][2]; if ( (c1 == j2.getSymb()) && ( (c3 == c2) && (c2 == RIEN) ) ) strat = sol[cases][1]; if ( (c2 == j2.getSymb()) && ( (c1 == c3) && (c1 == RIEN) ) ) strat = sol[cases][0]; } } } // Méthode qui détermine si un symbole à gagné ou si match nul // Parcours tab pour voir si il reste des cases vides // Puis parcours le tableau des combinaisons gagnantes et regarde si // le symbole reçu en argument en a fait une. // si oui -> renvoit 1 // si non -> renvoit 0 si il reste des cases vides ou 2 si match nul // Reçoit le symbole du joueur qui vient juste de jouer public int regles(int symbCur) { int cases = 0,c1,c2,c3,parc; parc = tab[cases++]; while ( (parc != RIEN) && (cases < 9) ) parc = tab[cases++]; for (cases = 0 ; cases < 8 ; cases++) { c1 = tab[sol[cases][0]]; c2 = tab[sol[cases][1]]; c3 = tab[sol[cases][2]]; if ( (c1 == symbCur) && ( (c2 == c1) && (c3 == c1) ) ) return 1; } if (parc == RIEN) return 0; else return 2; } } /***************************************************************** Classe Paneau permettant la création de JPanel personnalisés. Ils contiennent : - un booleen permettant de savoir si il sont deja dessinés - une référence à la partie en cours - un indice (correspondance avec les cases du tableau tab) - la valeur du symbole dessiné
                                                                                                                                    • /
class Paneau extends JPanel { private boolean dejDess = false; private Partie _part; private int _indice; private int symbo = 2; // Constructeur de Paneau // Reçoit une référence à la partie et son indice public Paneau(Partie part, int indice) { _indice = indice; _part = part; setSize(60,60); setBackground(Color.lightGray); // Ajoute un MouseListener (écouteur de souris) qui va // intercepter les clicks sur le Paneau addMouseListener(new MouseAdapter() { // Définition de la méthode mouseClicked qui sera // automatiquement appelée quand il y aura un click //c'est la commande new MouseAdapter qui permet //de la définir de suite public void mouseClicked(MouseEvent e) { if (_part.getIsRunning()) _part.jeu((Paneau)e.getSource()); } }); } // Méthode qui renvoit le symbole du Paneau public int getSymbo() { return symbo; } // Méthode qui affecte le symbole du Paneau public void setSymbo(int symb) { symbo = symb; } // Méthode qui renvoit l'état du Paneau (déssiné oui / non ) public boolean getDejDess() { return dejDess; } // Méthode qui affecte l'état du Paneau public void setDejDess(boolean etat) { dejDess = etat; } // Méthode qui renvoit l'indice du Paneau public int getIndice() { return _indice; } // Méthode qui est appelé à la création d'un Paneau et // dès que l'on fait un Paneau.repaint() public void paintComponent(Graphics g) { // Appel de la méthode paintComponent de la classe parente super.paintComponent(g); if (symbo == _part.CROIX) { // Dessine une croix g.setColor(Color.blue); g.drawLine(5,5,50,50); g.drawLine(50,5,5,50); } if (symbo == _part.ROND) { // Dessine un rond g.setColor(Color.yellow); g.drawOval(5,5,this.getWidth()-5,this.getHeight()-5); } } } /***************************************************************** Classe Jouer qui contient le programme principal permettant de jouer -> la méthode main qui sera lancée automatiquement.
                                                                                                                                    • /
public class Jouer { public static void main(String[] args) { // Création d'une fenetre MorpionFrame MorpionFrame morp = new MorpionFrame(); morp.setSize(190,250); // Récupère la taille de l'écran pour centrer la fenetre Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); morp.setLocation((screenSize.width-morp.getWidth())/2,(screenSize.height-morp.getHeight())/2); morp.setVisible(true); } }

Conclusion :


Bon, je pense que le code peut encore etre optimisé !!
Soyez indulgents :)
Donnez moi votre avis et vos critiques.

Duss

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.