Dans ce tutoriel, tu vas créer un jeu du Morpion en Java (Tic-Tac-Toe) avec Swing et NetBeans : un plateau 3×3 cliquable, la détection du gagnant ou de l’égalité et un bouton pour recommencer. Un projet idéal pour progresser en Java, découvrir Swing et apprendre à séparer la logique du jeu de l’interface.

Niveau : débutantDurée : ~1 hJava · Swing · NetBeansCode complet inclus
Jeu du Morpion en Java avec Swing : plateau 3x3 avec des X et des O
Le résultat final : une partie de Morpion dans une fenêtre Swing

Ce que tu vas construire : un jeu du Morpion en Java

Marre des « Hello World » ? Ce jeu du Morpion en Java est un vrai petit jeu qui fonctionne, avec une logique solide et une interface graphique. Tu y apprendras des compétences utiles, que tu sois étudiant, développeur en herbe ou simplement curieux.

⬜ Plateau 3×3Neuf boutons cliquables disposés en grille.
❌⭕ Deux joueursX et O jouent à tour de rôle sur le même ordinateur.
🏆 Gagnant ou égalitéUn message annonce le résultat de la partie.
🔄 RecommencerUn bouton remet le plateau à zéro.

Prérequis

  • Un JDK installé (Java 8 ou plus récent)
  • L’IDE Apache NetBeans (ou un autre IDE Java comme IntelliJ IDEA ou Eclipse)
  • Les bases de Java : classes, méthodes, tableaux et conditions

Étape 1 : créer le projet dans NetBeans

  • Ouvre NetBeans et crée un nouveau projet Java Application nommé TicTacToe
  • Dans le dossier Source Packages, ajoute un nouveau package :
com.myapp.tictactoe
package

Ton jeu du Morpion en Java repose sur deux classes à créer dans ce package :

TicTacToe/ └── src/com/myapp/tictactoe/ ├── GameModel.java # la logique du jeu └── GameView.java # l’interface graphique Swing
ℹ️
Pourquoi deux classes ?

On sépare la logique (le modèle) de l’affichage (la vue). C’est une version simplifiée du modèle MVC : le code est plus clair, plus facile à tester et à faire évoluer.

Étape 2 : GameModel.java, le cerveau du jeu

Cette classe gère toute la logique de ton jeu du Morpion en Java : le plateau, le joueur actuel, la vérification du gagnant et les changements de tour.

package com.myapp.tictactoe;

public class GameModel {
    public enum Player { X, O, NONE }
    private Player[] board = new Player[9];
    private Player currentPlayer = Player.X;
    private boolean gameOver = false;

    public GameModel() { reset(); }

    public void reset() {
        for (int i = 0; i < 9; i++) board[i] = Player.NONE;
        currentPlayer = Player.X;
        gameOver = false;
    }

    public Player getCurrentPlayer() { return currentPlayer; }
    public Player getCell(int idx) { return board[idx]; }
    public boolean isGameOver() { return gameOver; }

    public Player playMove(int idx) {
        if (gameOver || board[idx] != Player.NONE) return null;
        board[idx] = currentPlayer;
        Player winner = checkWinner();
        if (winner != Player.NONE) {
            gameOver = true;
            return winner;
        }
        if (isBoardFull()) {
            gameOver = true;
            return Player.NONE; // match nul
        }
        currentPlayer = (currentPlayer == Player.X) ? Player.O : Player.X;
        return null;
    }

    private boolean isBoardFull() {
        for (Player p : board)
            if (p == Player.NONE) return false;
        return true;
    }

    private Player checkWinner() {
        int[][] lines = {
            {0,1,2},{3,4,5},{6,7,8},
            {0,3,6},{1,4,7},{2,5,8},
            {0,4,8},{2,4,6}
        };
        for (int[] line : lines) {
            Player a = board[line[0]], b = board[line[1]], c = board[line[2]];
            if (a != Player.NONE && a == b && b == c) return a;
        }
        return Player.NONE;
    }
}
GameModel.java
  • Le plateau est un tableau de 9 cases
  • L’enum Player distingue clairement X, O et une case vide (NONE)
  • La méthode playMove() joue le rôle d’arbitre : elle accepte ou refuse le coup et indique s’il y a un gagnant ou une égalité
  • Impossible de tricher : une case déjà prise ne peut pas être rejouée

Étape 3 : GameView.java, l’interface graphique Swing

Maintenant que le cerveau du jeu du Morpion en Java est prêt, il faut le corps : l’interface que les joueurs utilisent pour poser leurs X et leurs O.

package com.myapp.tictactoe;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GameView extends JFrame {
    private GameModel model = new GameModel();
    private JButton[] cells = new JButton[9];
    private JLabel statusLabel = new JLabel("Au tour de X");
    private JButton resetBtn = new JButton("Recommencer");

    public GameView() {
        super("Morpion");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout(10,10));
        JPanel grid = new JPanel(new GridLayout(3,3,5,5));
        for (int i = 0; i < 9; i++) {
            final int idx = i;
            cells[i] = new JButton("");
            cells[i].setFont(new Font(Font.SANS_SERIF, Font.BOLD, 48));
            cells[i].addActionListener(e -> handleClick(idx));
            grid.add(cells[i]);
        }
        JPanel bottom = new JPanel();
        bottom.add(statusLabel);
        bottom.add(resetBtn);
        resetBtn.addActionListener(e -> initGame());

        add(grid, BorderLayout.CENTER);
        add(bottom, BorderLayout.SOUTH);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void initGame() {
        model.reset();
        statusLabel.setText("Au tour de X");
        for (JButton b : cells) {
            b.setText("");
            b.setEnabled(true);
        }
    }

    private void handleClick(int idx) {
        GameModel.Player winner = model.playMove(idx);
        GameModel.Player p = model.getCell(idx);
        cells[idx].setText(p == GameModel.Player.X ? "X" : "O");
        if (winner != null) {
            if (winner == GameModel.Player.NONE) {
                statusLabel.setText("Match nul.");
            } else {
                statusLabel.setText("Le joueur " + winner + " a gagné !");
            }
            disableAll();
        } else {
            statusLabel.setText("Au tour de " + model.getCurrentPlayer());
        }
    }

    private void disableAll() {
        for (JButton b : cells) b.setEnabled(false);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(GameView::new);
    }
}
GameView.java
GridLayoutUn JPanel en grille 3×3 accueille les neuf boutons.
handleClick()Chaque clic transmet le coup au modèle et met à jour l’affichage.
RecommencerRemet le jeu à zéro pour une nouvelle partie.
invokeLater()SwingUtilities.invokeLater() lance l’interface sur le bon thread, comme le recommande Swing.

Étape 4 : lancer le jeu du Morpion en Java

  • Clique sur Run Project (ou F6) dans NetBeans
  • Une fenêtre s’ouvre avec le plateau 3×3
  • Joue une partie : les X et les O s’affichent à chaque clic, puis un message annonce le vainqueur ou l’égalité
  • Clique sur « Recommencer » pour rejouer

Aller plus loin

FAQ : questions fréquentes

Faut-il absolument utiliser NetBeans ?

Non. Le code fonctionne dans n’importe quel IDE Java (IntelliJ IDEA, Eclipse, VS Code avec l’extension Java). Il suffit de respecter le package com.myapp.tictactoe.

Pourquoi utiliser SwingUtilities.invokeLater() ?

Swing n’est pas thread-safe : toute modification de l’interface doit se faire sur le thread dédié à l’affichage. invokeLater() garantit que la fenêtre est créée au bon endroit.

Comment le jeu détecte-t-il une égalité ?

Quand toutes les cases sont remplies et qu’aucune ligne, colonne ou diagonale n’est complète, la partie est déclarée nulle.

Swing est-il encore utilisé ?

Swing reste très présent dans l’enseignement et dans de nombreuses applications existantes. Pour un projet moderne, JavaFX est une bonne alternative.

Bravo, ton jeu du Morpion en Java est terminé ! Tu as découvert Swing et appris à séparer la logique de l’interface. Partage ta version ou tes questions en commentaire !

1 Comment

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *