Bonsoir à tous,
Actuellement en L3 info spécialité développement, j'ai voulu me lancer de mon côté dans la réalisation d'un jeu d'échec. J'ai pour l'instant commencé à implémenter les classes suivantes :
- une classe abstraite Piece dont hériteront toutes les pièces. La classe Piece implémente les méthodes déplacer (que j'ai découpé pour l'instant en déplacement horizontal et vertical seulement, je pense créer ensuite une méthode déplacement en diagonale), une méthode deplacementCorrect redéfinie dans chacune des classes héritant de Piece et une méthode prendre, elle aussi à redéfinir.
- une classe Square qui représente une case dans l'échiquier. Je lui attribue une couleur, un booléen pour savoir si elle est occupée, une coordonnée X et une coordonnée Y ainsi qu'un JPanel sur lequel je compte afficher la pièce.
- une classe Pion qui me sert pour l'instant de test, elle n'implémente qu'une fonction deplacementCorrect pour l'instant, prenant en compte les spécificités d'un pion pour se déplacer.
- enfin une classe Fenetre, elle possède un tableau de Square[8][8] faisant office d'échiquier. Ses méthodes initFrame et initChessboard permettent de créer la fenêtre et de colorier les cases de l'échiquier. Je tiens à préciser que la méthode displayPiece(Piece piece) est vouée à disparaître, elle me sert simplement pour l'instant car je ne souhaite n'afficher qu'une pièce et réussir à la faire se déplacer.
A terme, je sais qu'une classe comme joueur qui possédera une liste de pièce est nécessaire mais je ne m'y suis pas encore attelé pour le moment.
Ma principale interrogation se situe au niveau de l'interface graphique. J'en ai déjà fait quelques une auparavant (un 2048 par exemple, c'était donc simpliste, les mouvements ne se géraient qu'au clavier ou encore un launcher pour une société mais la encore, il n'y avait pas de MouseListener) mais je n'ai jamais utilisé réellement l'interface MouseListener. Je ne sais pas où mettre l'implémentation des méthodes de cette interface dans mon code. J'ai essayé d'associer à chaque JPanel un mouseListener en faisantmais je n'y arrive pas. Je peux sélectionner la pièce mais je ne peux pas la déplacer car forcément, lorsque je clique sur un autre JPanel, je ne l'ai plus. Peut être que l'on peut faire de cette manière mais que mon code est mauvais, je ne sais pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part chessboard[i][j].getSquare().addMouseListener(new MouseListener() { ... }
J'ai parcouru la discussion suivante http://www.developpez.net/forums/d13...chiquier-java/ et j'ai vu que la personne utilisait une classe privée, est-ce une bonne manière de faire ?
N'étant qu'au début de mon projet, je suis ouvert à toute remarque car je préfère partir dans la direction la plus "propre" possible. Mes interrogations sont surtout au niveau de la partie graphique car il me semble que la partie fonctionnelle (les pièces, les mouvements) est assez claire, même si je sais que certains préféreraient utiliser une classe Deplacement.
En bref, n'importe quelle remarque, qu'elle porte sur le fonctionnel ou l'IHM m'intéresse. N'hésitez donc pas à me dire si quelque chose vous fait hurler
Ci-joint les 4 classes que j'ai pour l'instant implémenté.
Classe Square (une case)
Classe Piece
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 package fonctionnel; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; public class Square { private Piece piece; private boolean black, occupied; private int positionX, positionY; private JPanel square; public Square(int positionX, int positionY, boolean black, boolean occupied) { this.black = black; this.occupied = occupied; this.positionX = positionX; this.positionY = positionY; square = new JPanel(); } public JPanel getSquare() { return square; } public void setSquareImage(String nomImage) { square.removeAll(); square.add(new JLabel(new ImageIcon(nomImage))); } public boolean isBlack() { return black; } public void setBlack(boolean black) { this.black = black; } public boolean isOccupied() { return occupied; } public void setOccupied(boolean occupied) { this.occupied = occupied; } public int getPositionX() { return positionX; } public void setPositionX(int positionX) { this.positionX = positionX; } public int getPositionY() { return positionY; } public void setPositionY(int positionY) { this.positionY = positionY; } public Piece getPiece() { return piece; } public void setPiece(Piece piece) { this.piece = piece; this.occupied = true; // C'est pas forcément beau, à voir si on garde comme ça } }
Classe Pawn
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 package fonctionnel; public abstract class Piece { protected String nomImage; protected int positionX, positionY; protected final int value; protected boolean black; public Piece(int valeur, int positionX, int positionY, boolean estNoir, String nom) { this.value = valeur; this.positionX = positionX; this.positionY = positionY; this.black = estNoir; this.nomImage = nom; } public boolean deplacer(Square board[][], int departX, int departY, int arriveeX, int arriveeY) { // la méthode renverra un boolean pour savoir si le déplacement a pu être effectué if(deplacementCorrect(board, departX, departY, arriveeX, arriveeY)) { board[departX][departY].setOccupied(false); board[arriveeX][arriveeY].setPiece(board[departX][departY].getPiece());// on déplace la pièce sur la case suivante board[arriveeX][arriveeY].setSquareImage(board[arriveeX][arriveeY].getPiece().getNom()); // On affiche la pièce sur la nouvelle case board[departX][departY].getSquare().removeAll(); // Suppression de l'image de la pièce board[departX][departY].setPiece(null); // on indique que la case dont par la pièce est désormais vide board[arriveeX][arriveeY].setOccupied(true); board[departX][departY].getSquare().repaint(); return true; } return false; } protected abstract boolean deplacementCorrect(Square board[][], int departX, int departY, int arriveeX, int arriveeY); // Méthode générique qui pourrait être réutilisé pour les pions, les tours, les reines et les rois // Un déplacement horizontal effectue un déplacement sur les abscisses protected boolean deplacementHorizontal(Square board[][], int departX, int departY, int arriveeX) { if(departX > arriveeX) // déplacement vers le bas { for(int i = departX-1; i > arriveeX; i--) // On part de la case à gauche de celle que l'on souhaite déplacer { if(board[i][departX].isOccupied()) // Si elle est occupée le déplacement est impossible { return false; // gérer le cas où l'on souhaite prendre la pièce } } return true; } else // déplacement vers le haut { for(int i = departX + 1; i <= arriveeX; i++) { if(board[i][departX].isOccupied()) return false; } return true; } } // Un déplacement vertical effectue un déplacement sur les ordonnées protected boolean deplacementVertical(Square board[][], int departX, int departY, int arriveeY) { if(departY > arriveeY) // déplacement vers la gauche { for(int i = departY - 1; i > arriveeY; i--) { if(board[i][departY].isOccupied()) return false; } return true; } else // déplacement vers la droite for(int i = departY + 1; i < arriveeY; i++) { if(board[i][departY].isOccupied()) return false; } return true; } protected void prendre() { } public int getPositionX() { return positionX; } public void setPositionX(int positionX) { this.positionX = positionX; } public int getPositionY() { return positionY; } public void setPositionY(int positionY) { this.positionY = positionY; } public String getNom() { return nomImage; } public void setNom(String nom) { this.nomImage = nom; } }
Classe Fenetre
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package fonctionnel; public class Pawn extends Piece { public Pawn(int positionX, int positionY, boolean estNoir) { super(1, positionX, positionY, estNoir, "pion"); //if(estNoir) // nom = "Images//" + nom + "Noir.jpg"; //else nomImage = "Images//" + nomImage + "Blanc.jpg"; } @Override protected boolean deplacementCorrect(Square board[][], int departX, int departY, int arriveeX, int arriveeY) { if(deplacementVertical(board, departX, departY, arriveeX) && (arriveeY - departY) == 1) // un pion ne peut se d�placer que d'une case { return true; } return false; } private void evoluer() { } }
Mon petit main de test
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 package interfaceGraphique; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import fonctionnel.Square; import fonctionnel.Piece; public class Fenetre implements MouseListener{ private final int dimension = 8; private JFrame frame = new JFrame("Echecs"); private Square chessboard[][] = new Square[dimension][dimension]; public Fenetre() { initChessboard(); initFrame(); frame.addMouseListener(this); } private void initFrame() { frame.setSize(800, 800); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setLayout(new GridLayout(8,8,1,1)); frame.setVisible(true); } private void initChessboard() { for(int j = dimension -1; j >= 0; j--)// boucle ordonnées { for(int i = 0; i < dimension ; i++) // boucle abscisses { if((i + j) % 2 == 0) // permet d'obtenir un vrai 1/2 ce que (j%2) ne permettait pas { chessboard[i][j] = new Square(i, j, true, false); chessboard[i][j].getSquare().setBackground(new Color(128, 64, 0)); } else { chessboard[i][j] = new Square(i, j, false, false); chessboard[i][j].getSquare().setBackground(new Color(250,224,124)); } chessboard[i][j].getSquare().setPreferredSize(new Dimension(50,50)); chessboard[i][j].getSquare().setBorder(BorderFactory.createLineBorder(Color.BLACK)); final int x = i, l = j; chessboard[i][j].getSquare().addMouseListener(new MouseListener() { Piece p; @Override public void mouseReleased(MouseEvent e) {} @Override public void mousePressed(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseClicked(MouseEvent e) { if(p == null) { p = chessboard[x][l].getPiece(); } else { try { if(chessboard[x][l].getPiece() == null) { System.out.println("ok"); chessboard[x][l].getPiece().deplacer(chessboard, x, l, x, l+1); frame.revalidate(); p = null; } else { System.out.println("case non vide"); } } catch(Exception ex){ System.out.println("case vide"); System.out.println("x : " + x + " y : " + l); } } } }); frame.add(chessboard[i][j].getSquare()); } } } public void displayPiece(Piece piece) { chessboard[piece.getPositionX()][piece.getPositionY()].getSquare().add(new JLabel(new ImageIcon("Images/pionBlanc.jpg"))); frame.revalidate(); } public Square getASquare(int i, int j) // ne retourne qu'une case de notre tableau, utilise pour set une piece { return chessboard[i][j]; } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } }
Merci d'avance pour votre aide
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 public static void main(String[] args) { Fenetre fenetre = new Fenetre(); Pawn pion = new Pawn(4,1,true); fenetre.displayPiece(pion); fenetre.getASquare(pion.getPositionX(), pion.getPositionY()).setPiece(pion); }
PS : J'ai finalement décidé pour ce projet de développer en utilisant la langue anglaise sauf pour les commentaires, si certaines variables ont encore un nom français, c'est un oubli de ma part
Partager