forked from menault/TD3_DEV51_Qualite_Algo
Compare commits
14 Commits
baab5c7ce2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ed2aaf669e | |||
| 2e88127e51 | |||
| 9c49c9e467 | |||
| dfa47463b1 | |||
| c3dc8f73ed | |||
| 3679e1a732 | |||
| 001cc1d32a | |||
| 3af3ed9e8a | |||
| d52b072c92 | |||
| 15061d6afd | |||
| 6943bafd1d | |||
| 37ebbcbdef | |||
| f3df0b36a9 | |||
| 15d048e21a |
263
HangmanGUI.java
Normal file
263
HangmanGUI.java
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hangman game GUI.
|
||||||
|
* Variables/methods and comments in English.
|
||||||
|
* User-facing texts remain in French.
|
||||||
|
*/
|
||||||
|
public class HangmanGUI extends JFrame {
|
||||||
|
private final String[] words = {
|
||||||
|
"ordinateur","voiture","maison","soleil","lumiere",
|
||||||
|
"fromage","chocolat","montagne","riviere","plage",
|
||||||
|
"oiseau","papillon","musique","chateau","livre",
|
||||||
|
"telephone","aventure","mystere","foret","fleur",
|
||||||
|
"chapeau","nuage","horloge","chaise","fenetre",
|
||||||
|
"paysage","bouteille","parapluie","clavier","souris",
|
||||||
|
"brouillard","village","histoire","cerise","pomme",
|
||||||
|
"banane","poisson","arbre","cascade","cheval"
|
||||||
|
};
|
||||||
|
|
||||||
|
private String secretWord;
|
||||||
|
private final Set<Character> found = new HashSet<>();
|
||||||
|
private final Set<Character> tried = new HashSet<>();
|
||||||
|
private int errors = 0;
|
||||||
|
private static final int MAX_ERRORS = 8; // 8 steps: base, post, beam, rope, head, body, arms, legs
|
||||||
|
private boolean gameOver = false; // indicates if the game is finished
|
||||||
|
|
||||||
|
private final JLabel wordLbl = new JLabel("", SwingConstants.CENTER);
|
||||||
|
private final JLabel triedLbl = new JLabel("", SwingConstants.CENTER);
|
||||||
|
private final JLabel infoLbl = new JLabel("Entrez une lettre (a-z)", SwingConstants.CENTER);
|
||||||
|
private final JTextField input = new JTextField();
|
||||||
|
private final JButton guessBtn = new JButton("Proposer");
|
||||||
|
private final HangPanel hangPanel = new HangPanel();
|
||||||
|
|
||||||
|
/** Drawing panel for the hangman, progressive according to error count. */
|
||||||
|
private static class HangPanel extends JPanel {
|
||||||
|
private int errors = 0;
|
||||||
|
|
||||||
|
public void setErrors(int e) {
|
||||||
|
this.errors = Math.max(0, Math.min(e, MAX_ERRORS));
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
Graphics2D gg = (Graphics2D) g;
|
||||||
|
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
int w = getWidth(), h = getHeight();
|
||||||
|
int baseY = h - 40; // ground level
|
||||||
|
|
||||||
|
if (errors >= 1) gg.drawLine(50, baseY, w - 50, baseY);
|
||||||
|
|
||||||
|
if (errors >= 2) gg.drawLine(100, baseY, 100, 60);
|
||||||
|
|
||||||
|
if (errors >= 3) gg.drawLine(100, 60, 220, 60);
|
||||||
|
|
||||||
|
if (errors >= 4) gg.drawLine(220, 60, 220, 90);
|
||||||
|
|
||||||
|
if (errors >= 5) gg.drawOval(200, 90, 40, 40);
|
||||||
|
|
||||||
|
if (errors >= 6) gg.drawLine(220, 130, 220, 200);
|
||||||
|
|
||||||
|
if (errors >= 7) {
|
||||||
|
gg.drawLine(220, 145, 190, 165);
|
||||||
|
gg.drawLine(220, 145, 250, 165);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors >= 8) {
|
||||||
|
gg.drawLine(220, 200, 200, 240);
|
||||||
|
gg.drawLine(220, 200, 240, 240);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Entry point: create and show the game window. */
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
HangmanGUI app = new HangmanGUI();
|
||||||
|
app.setVisible(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constructor: window setup, UI setup, and start the game. */
|
||||||
|
public HangmanGUI() {
|
||||||
|
super("Jeu du Pendu");
|
||||||
|
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||||
|
setSize(520, 520);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
setupUI();
|
||||||
|
startGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Prepare the layout and interactions. */
|
||||||
|
private void setupUI() {
|
||||||
|
wordLbl.setFont(new Font(Font.MONOSPACED, Font.BOLD, 28));
|
||||||
|
triedLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
|
||||||
|
infoLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
|
||||||
|
|
||||||
|
JPanel top = new JPanel(new GridLayout(3, 1, 8, 8));
|
||||||
|
top.add(wordLbl);
|
||||||
|
top.add(triedLbl);
|
||||||
|
top.add(infoLbl);
|
||||||
|
|
||||||
|
JPanel controls = new JPanel(new BorderLayout(8, 8));
|
||||||
|
controls.add(input, BorderLayout.CENTER);
|
||||||
|
controls.add(guessBtn, BorderLayout.EAST);
|
||||||
|
|
||||||
|
hangPanel.setPreferredSize(new Dimension(480, 300));
|
||||||
|
JPanel center = new JPanel(new BorderLayout());
|
||||||
|
center.add(hangPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel main = new JPanel(new BorderLayout(10, 10));
|
||||||
|
main.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
main.add(top, BorderLayout.NORTH);
|
||||||
|
main.add(center, BorderLayout.CENTER);
|
||||||
|
main.add(controls, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
setContentPane(main);
|
||||||
|
|
||||||
|
guessBtn.addActionListener(e -> onGuess());
|
||||||
|
input.addActionListener(e -> onGuess());
|
||||||
|
addWindowListener(new WindowAdapter() {
|
||||||
|
@Override public void windowOpened(WindowEvent e) { input.requestFocusInWindow(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Start a game. */
|
||||||
|
private void startGame() {
|
||||||
|
secretWord = pickWord();
|
||||||
|
found.clear();
|
||||||
|
tried.clear();
|
||||||
|
errors = 0;
|
||||||
|
gameOver = false;
|
||||||
|
|
||||||
|
input.setText("");
|
||||||
|
input.setEditable(true);
|
||||||
|
guessBtn.setEnabled(true);
|
||||||
|
infoLbl.setText("Entrez une lettre (a-z)");
|
||||||
|
updateUIState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handle a guess: validate input, update state, check for end of game. */
|
||||||
|
private void onGuess() {
|
||||||
|
if (gameOver) return; // block input after game end
|
||||||
|
|
||||||
|
String s = input.getText().trim().toLowerCase(Locale.ROOT);
|
||||||
|
if (s.length() != 1 || s.charAt(0) < 'a' || s.charAt(0) > 'z') {
|
||||||
|
infoLbl.setText("Veuillez entrer une seule lettre (a-z).");
|
||||||
|
input.selectAll();
|
||||||
|
input.requestFocusInWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char c = s.charAt(0);
|
||||||
|
if (tried.contains(c)) {
|
||||||
|
infoLbl.setText("Lettre déjà essayée : " + c);
|
||||||
|
input.selectAll();
|
||||||
|
input.requestFocusInWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tried.add(c);
|
||||||
|
boolean hit = false;
|
||||||
|
for (int i = 0; i < secretWord.length(); i++) {
|
||||||
|
if (Character.toLowerCase(secretWord.charAt(i)) == c) {
|
||||||
|
found.add(c);
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hit) {
|
||||||
|
errors++;
|
||||||
|
infoLbl.setText("Mauvaise lettre : " + c);
|
||||||
|
} else {
|
||||||
|
infoLbl.setText("Bonne lettre : " + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUIState();
|
||||||
|
input.selectAll();
|
||||||
|
input.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Refresh labels/drawing and handle end-of-game. */
|
||||||
|
private void updateUIState() {
|
||||||
|
wordLbl.setText(maskWord(secretWord, found));
|
||||||
|
triedLbl.setText("Lettres essayées : " + joinChars(tried));
|
||||||
|
hangPanel.setErrors(errors);
|
||||||
|
|
||||||
|
if (isWin(secretWord, found)) {
|
||||||
|
infoLbl.setText("Bravo ! Vous avez trouvé le mot : " + secretWord);
|
||||||
|
wordLbl.setText(spaced(secretWord)); // pretty display of the word
|
||||||
|
gameOver = true;
|
||||||
|
disableInput();
|
||||||
|
} else if (errors >= MAX_ERRORS) {
|
||||||
|
infoLbl.setText("Perdu ! Le mot était : " + secretWord);
|
||||||
|
wordLbl.setText(spaced(secretWord));
|
||||||
|
gameOver = true;
|
||||||
|
disableInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// force UI refresh
|
||||||
|
revalidate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Disable controls after the game ends. */
|
||||||
|
private void disableInput() {
|
||||||
|
input.setEditable(false);
|
||||||
|
guessBtn.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pick a random word. */
|
||||||
|
private String pickWord() {
|
||||||
|
Random rnd = new Random();
|
||||||
|
return words[rnd.nextInt(words.length)].toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Build the masked word based on found letters. */
|
||||||
|
private String maskWord(String secret, Set<Character> foundSet) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < secret.length(); i++) {
|
||||||
|
char ch = secret.charAt(i);
|
||||||
|
char lc = Character.toLowerCase(ch);
|
||||||
|
if (Character.isLetter(lc) && !foundSet.contains(lc)) sb.append('_');
|
||||||
|
else sb.append(ch);
|
||||||
|
if (i < secret.length() - 1) sb.append(' ');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** True if all letters have been found. */
|
||||||
|
private boolean isWin(String secret, Set<Character> foundSet) {
|
||||||
|
for (int i = 0; i < secret.length(); i++) {
|
||||||
|
char lc = Character.toLowerCase(secret.charAt(i));
|
||||||
|
if (Character.isLetter(lc) && !foundSet.contains(lc)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sort and join letters for display. */
|
||||||
|
private String joinChars(Set<Character> set) {
|
||||||
|
java.util.List<Character> list = new ArrayList<>(set);
|
||||||
|
Collections.sort(list);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
sb.append(list.get(i));
|
||||||
|
if (i < list.size() - 1) sb.append(' ');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add spaces between letters for nicer reading. */
|
||||||
|
private String spaced(String s) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
sb.append(s.charAt(i));
|
||||||
|
if (i < s.length() - 1) sb.append(' ');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#FACILE
|
#EASY
|
||||||
banane
|
banane
|
||||||
ceinture
|
ceinture
|
||||||
maman
|
maman
|
||||||
@@ -219,7 +219,7 @@ clef
|
|||||||
terre
|
terre
|
||||||
voisine
|
voisine
|
||||||
chapeau
|
chapeau
|
||||||
#MOYEN
|
#MEDIUM
|
||||||
serpent
|
serpent
|
||||||
orage
|
orage
|
||||||
bracelet
|
bracelet
|
||||||
@@ -400,7 +400,7 @@ salon
|
|||||||
siege
|
siege
|
||||||
garage
|
garage
|
||||||
poesie
|
poesie
|
||||||
#DIFFICILE
|
#HARD
|
||||||
adaptation
|
adaptation
|
||||||
paradoxe
|
paradoxe
|
||||||
imaginatif
|
imaginatif
|
||||||
Binary file not shown.
@@ -1,51 +0,0 @@
|
|||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class GestionMotsPendu {
|
|
||||||
|
|
||||||
private static final String CHEMIN_FICHIER = "../res/mots_pendu.txt";
|
|
||||||
|
|
||||||
private final Map<String, List<String>> motsParDifficulte = new HashMap<>();
|
|
||||||
|
|
||||||
public GestionMotsPendu() throws IOException {
|
|
||||||
motsParDifficulte.put("FACILE", new ArrayList<>());
|
|
||||||
motsParDifficulte.put("MOYEN", new ArrayList<>());
|
|
||||||
motsParDifficulte.put("DIFFICILE", new ArrayList<>());
|
|
||||||
chargerMots();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void chargerMots() throws IOException {
|
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(CHEMIN_FICHIER))) {
|
|
||||||
String ligne;
|
|
||||||
String section = "";
|
|
||||||
while ((ligne = reader.readLine()) != null) {
|
|
||||||
ligne = ligne.trim();
|
|
||||||
if (ligne.startsWith("#")) {
|
|
||||||
section = ligne.substring(1).toUpperCase();
|
|
||||||
} else if (!ligne.isEmpty() && motsParDifficulte.containsKey(section)) {
|
|
||||||
motsParDifficulte.get(section).add(ligne);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new IOException("Fichier introuvable : " + CHEMIN_FICHIER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMotAleatoire(int difficulte) {
|
|
||||||
String cle = convertirDifficulte(difficulte);
|
|
||||||
List<String> liste = motsParDifficulte.get(cle);
|
|
||||||
if (liste == null || liste.isEmpty()) return null;
|
|
||||||
|
|
||||||
Random rand = new Random();
|
|
||||||
return liste.get(rand.nextInt(liste.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String convertirDifficulte(int difficulte) {
|
|
||||||
return switch (difficulte) {
|
|
||||||
case 1 -> "FACILE";
|
|
||||||
case 2 -> "MOYEN";
|
|
||||||
case 3 -> "DIFFICILE";
|
|
||||||
default -> "FACILE"; // Valeur par défaut
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
321
src/HangmanGUI.java
Normal file
321
src/HangmanGUI.java
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
/**
|
||||||
|
* Hangman GUI with difficulty selection, dynamic score, and timer.
|
||||||
|
* Uses WordManager for words.
|
||||||
|
* User-facing texts remain in French.
|
||||||
|
*/
|
||||||
|
public class HangmanGUI extends JFrame {
|
||||||
|
private WordManager manager;
|
||||||
|
private String secretWord;
|
||||||
|
private final Set<Character> found = new HashSet<>();
|
||||||
|
private final Set<Character> tried = new HashSet<>();
|
||||||
|
private int errors = 0;
|
||||||
|
private static final int MAX_ERRORS = 8;
|
||||||
|
private static final int WORD_GUESS_PENALTY = 2; // pénalité (en erreurs) si le mot complet proposé est faux
|
||||||
|
private boolean gameOver = false;
|
||||||
|
|
||||||
|
// scoring and timing
|
||||||
|
private int baseScore = 200;
|
||||||
|
private int mistakePenalty = 15;
|
||||||
|
private double timePenaltyPerSecond = 1.0;
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
|
// UI components
|
||||||
|
private final JLabel wordLbl = new JLabel("", SwingConstants.CENTER);
|
||||||
|
private final JLabel triedLbl = new JLabel("", SwingConstants.CENTER);
|
||||||
|
private final JLabel infoLbl = new JLabel("Entrez une lettre ou un mot (a-z)", SwingConstants.CENTER);
|
||||||
|
private final JLabel scoreLbl = new JLabel("Score: 0", SwingConstants.CENTER);
|
||||||
|
private final JLabel timerLbl = new JLabel("Temps: 0s", SwingConstants.CENTER);
|
||||||
|
private final JTextField input = new JTextField();
|
||||||
|
private final JButton guessBtn = new JButton("Proposer");
|
||||||
|
private final HangPanel hangPanel = new HangPanel();
|
||||||
|
private final String[] difficulties = {"Facile", "Moyen", "Difficile"};
|
||||||
|
private final JComboBox<String> difficultyCombo = new JComboBox<>(difficulties);
|
||||||
|
private Timer timer;
|
||||||
|
|
||||||
|
/** Drawing panel for hangman */
|
||||||
|
private static class HangPanel extends JPanel {
|
||||||
|
private int errors = 0;
|
||||||
|
public void setErrors(int e) {
|
||||||
|
this.errors = Math.max(0, Math.min(e, MAX_ERRORS));
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
Graphics2D gg = (Graphics2D) g;
|
||||||
|
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
int w = getWidth(), h = getHeight();
|
||||||
|
int baseY = h - 40;
|
||||||
|
if (errors >= 1) gg.drawLine(50, baseY, w - 50, baseY);
|
||||||
|
if (errors >= 2) gg.drawLine(100, baseY, 100, 60);
|
||||||
|
if (errors >= 3) gg.drawLine(100, 60, 220, 60);
|
||||||
|
if (errors >= 4) gg.drawLine(220, 60, 220, 90);
|
||||||
|
if (errors >= 5) gg.drawOval(200, 90, 40, 40);
|
||||||
|
if (errors >= 6) gg.drawLine(220, 130, 220, 200);
|
||||||
|
if (errors >= 7) {
|
||||||
|
gg.drawLine(220, 145, 190, 165);
|
||||||
|
gg.drawLine(220, 145, 250, 165);
|
||||||
|
}
|
||||||
|
if (errors >= 8) {
|
||||||
|
gg.drawLine(220, 200, 200, 240);
|
||||||
|
gg.drawLine(220, 200, 240, 240);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Entry point */
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
try {
|
||||||
|
HangmanGUI app = new HangmanGUI();
|
||||||
|
app.setVisible(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Constructor */
|
||||||
|
public HangmanGUI() throws Exception {
|
||||||
|
super("Jeu du Pendu");
|
||||||
|
manager = new WordManager();
|
||||||
|
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||||
|
setSize(560, 620);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
setupUI();
|
||||||
|
startGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Setup UI */
|
||||||
|
private void setupUI() {
|
||||||
|
wordLbl.setFont(new Font(Font.MONOSPACED, Font.BOLD, 28));
|
||||||
|
triedLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
|
||||||
|
infoLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
|
||||||
|
scoreLbl.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||||
|
timerLbl.setFont(new Font("SansSerif", Font.BOLD, 16));
|
||||||
|
|
||||||
|
JPanel top = new JPanel(new GridLayout(6, 1, 8, 8));
|
||||||
|
top.add(wordLbl);
|
||||||
|
top.add(triedLbl);
|
||||||
|
top.add(infoLbl);
|
||||||
|
|
||||||
|
JPanel scorePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5));
|
||||||
|
scorePanel.add(scoreLbl);
|
||||||
|
scorePanel.add(timerLbl);
|
||||||
|
top.add(scorePanel);
|
||||||
|
|
||||||
|
JPanel diffPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||||
|
diffPanel.add(new JLabel("Difficulté:"));
|
||||||
|
diffPanel.add(difficultyCombo);
|
||||||
|
top.add(diffPanel);
|
||||||
|
|
||||||
|
JButton restartBtn = new JButton("Rejouer");
|
||||||
|
restartBtn.addActionListener(e -> startGame());
|
||||||
|
JPanel restartPanel = new JPanel();
|
||||||
|
restartPanel.add(restartBtn);
|
||||||
|
top.add(restartPanel);
|
||||||
|
|
||||||
|
JPanel controls = new JPanel(new BorderLayout(8, 8));
|
||||||
|
controls.add(input, BorderLayout.CENTER);
|
||||||
|
controls.add(guessBtn, BorderLayout.EAST);
|
||||||
|
|
||||||
|
hangPanel.setPreferredSize(new Dimension(500, 300));
|
||||||
|
|
||||||
|
JPanel center = new JPanel(new BorderLayout());
|
||||||
|
center.add(hangPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel main = new JPanel(new BorderLayout(10, 10));
|
||||||
|
main.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
main.add(top, BorderLayout.NORTH);
|
||||||
|
main.add(center, BorderLayout.CENTER);
|
||||||
|
main.add(controls, BorderLayout.SOUTH);
|
||||||
|
setContentPane(main);
|
||||||
|
|
||||||
|
guessBtn.addActionListener(e -> onGuess());
|
||||||
|
input.addActionListener(e -> onGuess());
|
||||||
|
addWindowListener(new WindowAdapter() {
|
||||||
|
@Override public void windowOpened(WindowEvent e) { input.requestFocusInWindow(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Start new game */
|
||||||
|
private void startGame() {
|
||||||
|
int diffIndex = difficultyCombo.getSelectedIndex(); // 0=Facile,1=Moyen,2=Difficile
|
||||||
|
int diffValue = diffIndex + 1;
|
||||||
|
secretWord = manager.getRandomWord(diffValue).toLowerCase(Locale.ROOT);
|
||||||
|
|
||||||
|
found.clear();
|
||||||
|
tried.clear();
|
||||||
|
errors = 0;
|
||||||
|
gameOver = false;
|
||||||
|
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
input.setText("");
|
||||||
|
input.setEditable(true);
|
||||||
|
guessBtn.setEnabled(true);
|
||||||
|
infoLbl.setText("Entrez une lettre ou un mot (a-z)");
|
||||||
|
|
||||||
|
updateUIState();
|
||||||
|
|
||||||
|
if (timer != null) timer.cancel();
|
||||||
|
timer = new Timer(true);
|
||||||
|
timer.scheduleAtFixedRate(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
updateScoreLabel();
|
||||||
|
updateTimerLabel();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 0, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handle guess (lettre OU mot) */
|
||||||
|
private void onGuess() {
|
||||||
|
if (gameOver) return;
|
||||||
|
|
||||||
|
String s = input.getText().trim().toLowerCase(Locale.ROOT);
|
||||||
|
|
||||||
|
// autoriser uniquement les lettres a-z, mais longueur libre (1 = lettre, >1 = mot)
|
||||||
|
if (!s.matches("[a-z]+")) {
|
||||||
|
infoLbl.setText("Veuillez entrer uniquement des lettres (a-z).");
|
||||||
|
input.selectAll();
|
||||||
|
input.requestFocusInWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.length() == 1) {
|
||||||
|
// === Proposition d'une lettre ===
|
||||||
|
char c = s.charAt(0);
|
||||||
|
if (tried.contains(c)) {
|
||||||
|
infoLbl.setText("Lettre déjà essayée : " + c);
|
||||||
|
input.selectAll();
|
||||||
|
input.requestFocusInWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tried.add(c);
|
||||||
|
|
||||||
|
boolean hit = false;
|
||||||
|
for (int i = 0; i < secretWord.length(); i++) {
|
||||||
|
if (secretWord.charAt(i) == c) {
|
||||||
|
found.add(c);
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hit) {
|
||||||
|
errors++;
|
||||||
|
infoLbl.setText("Mauvaise lettre : " + c);
|
||||||
|
} else {
|
||||||
|
infoLbl.setText("Bonne lettre : " + c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// === Proposition d'un mot entier ===
|
||||||
|
if (s.equals(secretWord)) {
|
||||||
|
// victoire immédiate : révéler tout
|
||||||
|
for (int i = 0; i < secretWord.length(); i++) {
|
||||||
|
char lc = secretWord.charAt(i);
|
||||||
|
if (Character.isLetter(lc)) found.add(lc);
|
||||||
|
}
|
||||||
|
infoLbl.setText("Bravo ! Vous avez deviné le mot en entier : " + secretWord);
|
||||||
|
} else {
|
||||||
|
// pénalité si mot faux
|
||||||
|
errors = Math.min(errors + WORD_GUESS_PENALTY, MAX_ERRORS);
|
||||||
|
infoLbl.setText("Mauvaise proposition du mot.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUIState();
|
||||||
|
input.selectAll();
|
||||||
|
input.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update UI */
|
||||||
|
private void updateUIState() {
|
||||||
|
wordLbl.setText(maskWord(secretWord, found));
|
||||||
|
triedLbl.setText("Lettres essayées : " + joinChars(tried));
|
||||||
|
hangPanel.setErrors(errors);
|
||||||
|
updateScoreLabel();
|
||||||
|
updateTimerLabel();
|
||||||
|
|
||||||
|
if (isWin(secretWord, found)) {
|
||||||
|
infoLbl.setText("Bravo ! Vous avez trouvé le mot : " + secretWord);
|
||||||
|
wordLbl.setText(spaced(secretWord));
|
||||||
|
gameOver = true;
|
||||||
|
disableInput();
|
||||||
|
} else if (errors >= MAX_ERRORS) {
|
||||||
|
infoLbl.setText("Perdu ! Le mot était : " + secretWord);
|
||||||
|
wordLbl.setText(spaced(secretWord));
|
||||||
|
gameOver = true;
|
||||||
|
disableInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update dynamic score */
|
||||||
|
private void updateScoreLabel() {
|
||||||
|
long elapsedMillis = System.currentTimeMillis() - startTime;
|
||||||
|
double elapsedSeconds = elapsedMillis / 1000.0;
|
||||||
|
int score = (int) (baseScore - errors * mistakePenalty - elapsedSeconds * timePenaltyPerSecond);
|
||||||
|
scoreLbl.setText("Score: " + Math.max(score, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update dynamic timer */
|
||||||
|
private void updateTimerLabel() {
|
||||||
|
long elapsedMillis = System.currentTimeMillis() - startTime;
|
||||||
|
int seconds = (int) (elapsedMillis / 1000);
|
||||||
|
timerLbl.setText("Temps: " + seconds + "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Disable input after end */
|
||||||
|
private void disableInput() {
|
||||||
|
input.setEditable(false);
|
||||||
|
guessBtn.setEnabled(false);
|
||||||
|
if (timer != null) timer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String maskWord(String secret, Set<Character> foundSet) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < secret.length(); i++) {
|
||||||
|
char ch = secret.charAt(i);
|
||||||
|
char lc = Character.toLowerCase(ch);
|
||||||
|
if (Character.isLetter(lc) && !foundSet.contains(lc)) sb.append('_');
|
||||||
|
else sb.append(ch);
|
||||||
|
if (i < secret.length() - 1) sb.append(' ');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWin(String secret, Set<Character> foundSet) {
|
||||||
|
for (int i = 0; i < secret.length(); i++) {
|
||||||
|
char lc = Character.toLowerCase(secret.charAt(i));
|
||||||
|
if (Character.isLetter(lc) && !foundSet.contains(lc)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String joinChars(Set<Character> set) {
|
||||||
|
java.util.List<Character> list = new ArrayList<>(set);
|
||||||
|
Collections.sort(list);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
sb.append(list.get(i));
|
||||||
|
if (i < list.size() - 1) sb.append(' ');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String spaced(String s) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
sb.append(s.charAt(i));
|
||||||
|
if (i < s.length() - 1) sb.append(' ');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -1,65 +0,0 @@
|
|||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class TestPendu {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
try {
|
|
||||||
Scanner scanner = new Scanner(System.in);
|
|
||||||
GestionMotsPendu gestion = new GestionMotsPendu();
|
|
||||||
|
|
||||||
System.out.println("Bienvenue dans le jeu du pendu !");
|
|
||||||
System.out.println("Choisissez la difficulté : 1 = Facile, 2 = Moyen, 3 = Difficile");
|
|
||||||
int difficulte = scanner.nextInt();
|
|
||||||
scanner.nextLine(); // consommer la fin de ligne
|
|
||||||
|
|
||||||
String mot = gestion.getMotAleatoire(difficulte);
|
|
||||||
if (mot == null) {
|
|
||||||
System.out.println("Erreur : aucun mot disponible pour cette difficulté.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] motCache = new char[mot.length()];
|
|
||||||
Arrays.fill(motCache, '_');
|
|
||||||
|
|
||||||
Set<Character> lettresDevinees = new HashSet<>();
|
|
||||||
int erreurs = 0;
|
|
||||||
int maxErreurs = 6;
|
|
||||||
|
|
||||||
while (erreurs < maxErreurs && new String(motCache).contains("_")) {
|
|
||||||
System.out.println("\nMot : " + new String(motCache));
|
|
||||||
System.out.println("Erreurs : " + erreurs + "/" + maxErreurs);
|
|
||||||
System.out.print("Devinez une lettre : ");
|
|
||||||
String input = scanner.nextLine().toLowerCase();
|
|
||||||
if (input.isEmpty()) continue;
|
|
||||||
|
|
||||||
char lettre = input.charAt(0);
|
|
||||||
if (lettresDevinees.contains(lettre)) {
|
|
||||||
System.out.println("Vous avez déjà essayé cette lettre !");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
lettresDevinees.add(lettre);
|
|
||||||
if (mot.indexOf(lettre) >= 0) {
|
|
||||||
for (int i = 0; i < mot.length(); i++) {
|
|
||||||
if (mot.charAt(i) == lettre) motCache[i] = lettre;
|
|
||||||
}
|
|
||||||
System.out.println("Bien joué !");
|
|
||||||
} else {
|
|
||||||
erreurs++;
|
|
||||||
System.out.println("Raté !");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new String(motCache).equals(mot)) {
|
|
||||||
System.out.println("\nFélicitations ! Vous avez trouvé le mot : " + mot);
|
|
||||||
} else {
|
|
||||||
System.out.println("\nVous avez perdu ! Le mot était : " + mot);
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner.close();
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Erreur lors du chargement des mots : " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
57
src/WordManager.java
Normal file
57
src/WordManager.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class WordManager {
|
||||||
|
|
||||||
|
// --- Constant: path to word file ---
|
||||||
|
private static final String WORD_FILE = "../res/hangman_words.txt";
|
||||||
|
|
||||||
|
// --- Map to store words by difficulty ---
|
||||||
|
private final Map<String, List<String>> wordsByDifficulty = new HashMap<>();
|
||||||
|
|
||||||
|
// --- Constructor ---
|
||||||
|
public WordManager() throws IOException {
|
||||||
|
wordsByDifficulty.put("EASY", new ArrayList<>());
|
||||||
|
wordsByDifficulty.put("MEDIUM", new ArrayList<>());
|
||||||
|
wordsByDifficulty.put("HARD", new ArrayList<>());
|
||||||
|
loadWords(); // automatically load words when created
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Load words from the file ---
|
||||||
|
private void loadWords() throws IOException {
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(WORD_FILE))) {
|
||||||
|
String line;
|
||||||
|
String section = "";
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
line = line.trim();
|
||||||
|
if (line.startsWith("#")) {
|
||||||
|
section = line.substring(1).toUpperCase(); // read difficulty section
|
||||||
|
} else if (!line.isEmpty() && wordsByDifficulty.containsKey(section)) {
|
||||||
|
wordsByDifficulty.get(section).add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new IOException("File not found: " + WORD_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Get a random word based on difficulty (1 = Easy, 2 = Medium, 3 = Hard) ---
|
||||||
|
public String getRandomWord(int difficulty) {
|
||||||
|
String key = difficultyToKey(difficulty);
|
||||||
|
List<String> list = wordsByDifficulty.get(key);
|
||||||
|
if (list == null || list.isEmpty()) return null;
|
||||||
|
|
||||||
|
Random rand = new Random();
|
||||||
|
return list.get(rand.nextInt(list.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Convert int to difficulty key ---
|
||||||
|
private String difficultyToKey(int difficulty) {
|
||||||
|
return switch (difficulty) {
|
||||||
|
case 1 -> "EASY";
|
||||||
|
case 2 -> "MEDIUM";
|
||||||
|
case 3 -> "HARD";
|
||||||
|
default -> "EASY"; // default difficulty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user