commit 8a8f39c6ce05fe176dc12c8a40c65c5d5a852ea2 Author: Dominik Krenn Date: Sun Oct 12 21:56:23 2025 +0200 initital commit UwU diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b468b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.class diff --git a/HangmanGUI.java b/HangmanGUI.java new file mode 100644 index 0000000..55d9947 --- /dev/null +++ b/HangmanGUI.java @@ -0,0 +1,115 @@ +import javax.swing.*; +import java.awt.*; +import java.io.*; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Scanner; + +public class HangmanGUI extends JFrame { + private HangmanGame game; + private JLabel wordLabel, historyLabel, statusLabel, imageLabel; + private JTextField input; + private JButton restartBtn; + private JCheckBoxMenuItem showHistoryItem; + private List words; + + public HangmanGUI() { + setTitle("Swing Hangman"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setSize(400, 500); + setLayout(new BorderLayout()); + + loadWords(); + game = new HangmanGame(words); + + // === Top Menu === + JMenuBar menuBar = new JMenuBar(); + JMenu settingsMenu = new JMenu("Settings"); + + JMenu triesMenu = new JMenu("Tries"); + int[] triesOptions = {3,6,9,12}; + for (int n : triesOptions) { + JMenuItem item = new JMenuItem(n + " tries"); + item.addActionListener(e -> { game.setMaxErrors(n); resetGame(); }); + triesMenu.add(item); + } + showHistoryItem = new JCheckBoxMenuItem("Show history", true); + showHistoryItem.addActionListener(e -> historyLabel.setVisible(showHistoryItem.isSelected())); + + settingsMenu.add(triesMenu); + settingsMenu.add(showHistoryItem); + menuBar.add(settingsMenu); + setJMenuBar(menuBar); + + // === Panels === + JPanel top = new JPanel(new GridLayout(4, 1)); + wordLabel = new JLabel("", SwingConstants.CENTER); + wordLabel.setFont(new Font("Monospaced", Font.BOLD, 24)); + historyLabel = new JLabel("", SwingConstants.CENTER); + statusLabel = new JLabel("Tries left: " + (game.getMaxErrors() - game.getErrors()), SwingConstants.CENTER); + imageLabel = new JLabel(new ImageIcon("img/hang0.png"), SwingConstants.CENTER); + + input = new JTextField(); + input.setHorizontalAlignment(JTextField.CENTER); + input.addActionListener(e -> handleGuess()); + restartBtn = new JButton("Restart"); + restartBtn.addActionListener(e -> resetGame()); + + top.add(wordLabel); + top.add(historyLabel); + top.add(statusLabel); + top.add(input); + + add(top, BorderLayout.NORTH); + add(imageLabel, BorderLayout.CENTER); + add(restartBtn, BorderLayout.SOUTH); + + refresh(); + setVisible(true); + } + + private void loadWords() { + words = new ArrayList<>(); + File f = new File("words.txt"); + if (f.exists()) { + try (Scanner sc = new Scanner(f)) { + while (sc.hasNext()) words.add(sc.next().trim()); + } catch (Exception e) { e.printStackTrace(); } + } + if (words.isEmpty()) { + words = Arrays.asList("JAVA", "SWING", "SQUIRREL", "PYTHON", "FLUFFY"); + } + } + + private void handleGuess() { + String text = input.getText().trim(); + if (text.length() == 0) return; + char c = text.charAt(0); + game.guess(c); + input.setText(""); + refresh(); + } + + private void refresh() { + wordLabel.setText(game.getMaskedWord()); + historyLabel.setText("History: " + game.getHistory()); + statusLabel.setText("Tries left: " + (game.getMaxErrors() - game.getErrors())); + imageLabel.setIcon(new ImageIcon("img/hang" + Math.min(game.getErrors(), 9) + ".png")); + + if (game.isWon()) { + JOptionPane.showMessageDialog(this, "Solved! Word was: " + game.getWord()); + } else if (game.isLost()) { + JOptionPane.showMessageDialog(this, "Game Over! Word was: " + game.getWord()); + } + } + + private void resetGame() { + game = new HangmanGame(words); + refresh(); + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(HangmanGUI::new); + } +} diff --git a/HangmanGame.java b/HangmanGame.java new file mode 100644 index 0000000..f971a43 --- /dev/null +++ b/HangmanGame.java @@ -0,0 +1,50 @@ +import java.util.*; + +public class HangmanGame { + private String word; + private Set guessed = new HashSet<>(); + private int errors = 0; + private int maxErrors = 9; + + public HangmanGame(List words) { + this.word = words.get(new Random().nextInt(words.size())).toUpperCase(); + } + + public void setMaxErrors(int max) { this.maxErrors = max; } + public int getErrors() { return errors; } + public int getMaxErrors() { return maxErrors; } + + public boolean guess(char c) { + c = Character.toUpperCase(c); + if (guessed.contains(c)) return true; + guessed.add(c); + if (!word.contains(String.valueOf(c))) errors++; + return isWon() || !isLost(); + } + + public String getMaskedWord() { + StringBuilder sb = new StringBuilder(); + for (char c : word.toCharArray()) { + sb.append(guessed.contains(c) ? c : '_'); + sb.append(' '); + } + return sb.toString(); + } + + public String getHistory() { + List list = new ArrayList<>(guessed); + Collections.sort(list); + StringBuilder sb = new StringBuilder(); + for (char c : list) sb.append(c).append(' '); + return sb.toString(); + } + + public boolean isWon() { + for (char c : word.toCharArray()) + if (!guessed.contains(c)) return false; + return true; + } + + public boolean isLost() { return errors >= maxErrors; } + public String getWord() { return word; } +} diff --git a/img/hang0.png b/img/hang0.png new file mode 100644 index 0000000..ad55ff9 Binary files /dev/null and b/img/hang0.png differ diff --git a/img/hang1.png b/img/hang1.png new file mode 100644 index 0000000..beb2daa Binary files /dev/null and b/img/hang1.png differ diff --git a/img/hang2.png b/img/hang2.png new file mode 100644 index 0000000..9180995 Binary files /dev/null and b/img/hang2.png differ diff --git a/img/hang3.png b/img/hang3.png new file mode 100644 index 0000000..26928cc Binary files /dev/null and b/img/hang3.png differ diff --git a/img/hang4.png b/img/hang4.png new file mode 100644 index 0000000..36a2b70 Binary files /dev/null and b/img/hang4.png differ diff --git a/img/hang5.png b/img/hang5.png new file mode 100644 index 0000000..c243317 Binary files /dev/null and b/img/hang5.png differ diff --git a/img/hang6.png b/img/hang6.png new file mode 100644 index 0000000..85b9b5a Binary files /dev/null and b/img/hang6.png differ diff --git a/img/hang7.png b/img/hang7.png new file mode 100644 index 0000000..3da6d17 Binary files /dev/null and b/img/hang7.png differ diff --git a/img/hang8.png b/img/hang8.png new file mode 100644 index 0000000..d6817ef Binary files /dev/null and b/img/hang8.png differ diff --git a/img/hang9.png b/img/hang9.png new file mode 100644 index 0000000..5aaa3a2 Binary files /dev/null and b/img/hang9.png differ diff --git a/words.txt b/words.txt new file mode 100644 index 0000000..cb035e6 --- /dev/null +++ b/words.txt @@ -0,0 +1,20 @@ +squirrel +nut +acorn +tree +fluff +tail +forest +nibble +chipper +oak +hazelnut +bushy +climb +autumn +hide +burrow +whiskers +branch +forage +nest