Programming Basics SQL HTML CSS JavaScript React Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Linux Learn Typing

Swingطريقة إنشاء لعبة Tic Tac Toe

المثال التالي يعلمك طريقة إنشاء لعبة ( Tic Tac Toe ) إحترافية باستخدام إطار الـ Swing.

java swing tic tac toe source code تحميل كود لعبة tic tac toe في جافا



مميزات اللعبة

  • يمكن لعب هذه اللعبة مع صديق أو ضد الكمبيوتر نفسه.
  • يمكن تعديل تصميمها بكل سهولة من داخل اللعبة.


بناء اللعبة

في هذا المشروع قمنا بوضع ملف الجافا بداخل مجلد إسمه tic_tac_toe.
و قمنا بوضع الصور بداخل مجلد إسمه images كما في الصورة التالية.

⇓ تحميل اللعبة ⇓ تحميل المشروع كاملاً ⇓ تحميل مجلد الصور فقط



كود اللعبة

Main.java
//  tic_tac_toe  موجود بداخل المجلد  Main.java   هنا ذكرنا أن الملف
package tic_tac_toe;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
 
// و بالتالي أصبح إنشاء كائن منه يمثل إنشاء نافذة JFrame يرث من الكلاس Main هنا جعلنا الكلاس
public class Main extends JFrame {
 
    // و الأشياء التي سنضعها فيها startPage هنا قمنا بتعريف الـ
    JPanel startPage;
    JButton startPage_singlePlayer;
    JButton startPage_multiPlayer;
    JButton startPage_settings;
    JButton startPage_about;
    JButton startPage_exit;
 
    // و الأشياء التي سنضعها فيها singlePlayerPage هنا قمنا بتعريف الـ
    JPanel singlePlayerPage;
    JLabel singlePlayerPage_label;
    JTextField singlePlayerPage_playerName;
    JButton singlePlayerPage_start;
    JButton singlePlayerPage_back;
 
    // و الأشياء التي سنضعها فيها multiPlayerPage هنا قمنا بتعريف الـ
    JPanel multiPlayerPage;
    JLabel multiPlayerPage_firstLabel;
    JLabel multiPlayerPage_secondLabel;
    JTextField multiPlayerPage_firstPlayerName;
    JTextField multiPlayerPage_secondPlayerName;
    JButton multiPlayerPage_start;
    JButton multiPlayerPage_back;
 
    // و الأشياء التي سنضعها فيها settingsPage هنا قمنا بتعريف الـ
    JPanel settingsPage;
    JLabel settingsPage_selectedBoardLabel;
    JComboBox settingsPage_selectedBoardValue;
    JLabel settingsPage_selectedFontSizeLabel;
    JComboBox settingsPage_selectedFontSizeValue;
    JButton settingsPage_reset;
    JButton settingsPage_back;
 
    // و الأشياء التي سنضعها فيها gamePage هنا قمنا بتعريف الـ
    JPanel gamePage;
    JPanel gamePage_boardPanel;
    JLabel[] gamePage_boardLabels;
    JLabel gamePage_boardBackground;
    JLabel gamePage_firstPlayerName;
    JLabel gamePage_secondPlayerName;
    JLabel gamePage_firstPlayerScore;
    JLabel gamePage_secondPlayerScore;
    JLabel gamePage_currentPlayerIcon;
    JButton gamePage_back;
    JButton gamePage_restart;
 
    // هنا قمنا بتعريف نوع الخط و حجم الخط و الألوان التي سنستخدمها في اللعبة
    Font defaultFont = new Font("Arial", Font.BOLD, 16);
    Color defaultButtonBackgroundColor = Color.lightGray;
    Color defaultButtonTextColor = Color.black;
    Color xForeground = Color.blue;
    Color oForeground = Color.red;
    Color winnerSquaresBackground = Color.yellow;
 
    // سنستخدم هذا المتغير لتحديد ما إذا كان شخص واحد سيلعب اللعبة أو إثنين
    boolean challengeComputer = false;
 
    // سنستخدم هذا المتغير لتحديد دور من في اللعب
    boolean isFirstPlayerTurn = true;
 
    // سنستخدم هذا المتغير لحساب عدد النقرات و بالتالي لتحديد ما إذا كان سيتم إيقاف اللعبة أم لا
    int XOCounter = 0;
 
    // سنستخدم هذا المتغير أيضاً لتحديد ما إذا كان سيتم إيقاف اللعبة بسبب فوز أحد اللاعبين
    boolean isGameEnds = false;
 
    // randomNumber لتوليد أرقام عشوائية عند اللعب ضد الكمبيوتر. و سنخزن الرقم في المتغير random سنستخدم الكائن
    Random random = new Random();
    int randomNumber;
 
 
    // سنستخدم هذه الدالة كلما أردنا تغيير حجم خط جميع الأزرار و النصوص الموجودة في اللعبة دفعة واحدة
    private void setNewFont(Font font) {
 
        startPage_singlePlayer.setFont(font);
        startPage_multiPlayer.setFont(font);
        startPage_settings.setFont(font);
        startPage_about.setFont(font);
        startPage_exit.setFont(font);
        singlePlayerPage_label.setFont(font);
        singlePlayerPage_playerName.setFont(font);
        singlePlayerPage_start.setFont(font);
        singlePlayerPage_back.setFont(font);
        multiPlayerPage_firstLabel.setFont(font);
        multiPlayerPage_secondLabel.setFont(font);
        multiPlayerPage_firstPlayerName.setFont(font);
        multiPlayerPage_secondPlayerName.setFont(font);
        multiPlayerPage_start.setFont(font);
        multiPlayerPage_back.setFont(font);
        settingsPage_selectedBoardLabel.setFont(font);
        settingsPage_selectedBoardValue.setFont(font);
        settingsPage_selectedFontSizeLabel.setFont(font);
        settingsPage_selectedFontSizeValue.setFont(font);
        settingsPage_reset.setFont(font);
        settingsPage_back.setFont(font);
        gamePage_boardPanel.setFont(font);
        gamePage_firstPlayerName.setFont(font);
        gamePage_secondPlayerName.setFont(font);
        gamePage_firstPlayerScore.setFont(font);
        gamePage_secondPlayerScore.setFont(font);
        gamePage_back.setFont(font);
        gamePage_restart.setFont(font);
 
    }
 
 
    // سنستخدم هذه الدالة كلما أردنا تغيير ألوان أزرار التطبيق
    private void setThemeColors(Color textColor, Color backgroundColor) {
 
        startPage_singlePlayer.setForeground(textColor);
        startPage_multiPlayer.setForeground(textColor);
        startPage_settings.setForeground(textColor);
        startPage_about.setForeground(textColor);
        startPage_exit.setForeground(textColor);
        startPage_singlePlayer.setBackground(backgroundColor);
        startPage_multiPlayer.setBackground(backgroundColor);
        startPage_settings.setBackground(backgroundColor);
        startPage_about.setBackground(backgroundColor);
        startPage_exit.setBackground(backgroundColor);
 
        singlePlayerPage_label.setForeground(textColor);
        singlePlayerPage_playerName.setForeground(textColor);
        singlePlayerPage_start.setForeground(textColor);
        singlePlayerPage_back.setForeground(textColor);
        singlePlayerPage_start.setBackground(backgroundColor);
        singlePlayerPage_back.setBackground(backgroundColor);
 
        multiPlayerPage_firstLabel.setForeground(textColor);
        multiPlayerPage_firstPlayerName.setForeground(textColor);
        multiPlayerPage_secondLabel.setForeground(textColor);
        multiPlayerPage_secondPlayerName.setForeground(textColor);
        multiPlayerPage_start.setForeground(textColor);
        multiPlayerPage_back.setForeground(textColor);
        multiPlayerPage_start.setBackground(backgroundColor);
        multiPlayerPage_back.setBackground(backgroundColor);
 
        gamePage_firstPlayerName.setForeground(textColor);
        gamePage_secondPlayerName.setForeground(textColor);
        gamePage_firstPlayerScore.setForeground(textColor);
        gamePage_secondPlayerScore.setForeground(textColor);
        gamePage_back.setForeground(textColor);
        gamePage_restart.setForeground(textColor);
        gamePage_restart.setBackground(backgroundColor);
        gamePage_back.setBackground(backgroundColor);
 
        settingsPage_selectedBoardLabel.setForeground(textColor);
        settingsPage_selectedBoardValue.setForeground(textColor);
        settingsPage_selectedFontSizeLabel.setForeground(textColor);
        settingsPage_selectedFontSizeValue.setForeground(textColor);
        settingsPage_reset.setForeground(textColor);
        settingsPage_back.setForeground(textColor);
        settingsPage_reset.setBackground(backgroundColor);
        settingsPage_back.setBackground(backgroundColor);
 
    }
 
 
    // startPage سنستخدم هذه الدالة لخلق محتوى الصفحة
    private void createStartPage() {
 
        // هنا أنشأنا الحاوية الأساسية و الأشياء التي سنضعها فيها
        startPage = new JPanel(null);
        startPage_singlePlayer = new JButton("Single Player");
        startPage_multiPlayer = new JButton("Multi Player");
        startPage_settings = new JButton("Settings");
        startPage_about = new JButton("About");
        startPage_exit = new JButton("Exit");
 
        // هنا وضعنا كل شيء بداخل الحاوية
        startPage.add(startPage_singlePlayer);
        startPage.add(startPage_multiPlayer);
        startPage.add(startPage_settings);
        startPage.add(startPage_about);
        startPage.add(startPage_exit);
 
        // هنا قمنا بتحديد حجم و موقع كل شيء أضفناه في الحاوية
        startPage_singlePlayer.setBounds(80, 110, 240, 40);
        startPage_multiPlayer.setBounds(80, 170, 240, 40);
        startPage_settings.setBounds(80, 230, 240, 40);
        startPage_about.setBounds(80, 290, 240, 40);
        startPage_exit.setBounds(80, 350, 240, 40);
 
    }
 
 
    // singlePlayerPage سنستخدم هذه الدالة لخلق محتوى الصفحة
    private void createSinglePlayerPage() {
 
        // هنا أنشأنا الحاوية الأساسية و الأشياء التي سنضعها فيها
        singlePlayerPage = new JPanel(null);
        singlePlayerPage_label = new JLabel("Player Name");
        singlePlayerPage_playerName = new JTextField("player");
        singlePlayerPage_start = new JButton("Start");
        singlePlayerPage_back = new JButton("Back");
 
        // هنا وضعنا كل شيء بداخل الحاوية
        singlePlayerPage.add(singlePlayerPage_label);
        singlePlayerPage.add(singlePlayerPage_playerName);
        singlePlayerPage.add(singlePlayerPage_start);
        singlePlayerPage.add(singlePlayerPage_back);
 
        // هنا قمنا بتحديد حجم و موقع كل شيء أضفناه في الحاوية
        singlePlayerPage_label.setBounds(80, 170, 100, 30);
        singlePlayerPage_playerName.setBounds(190, 170, 130, 30);
        singlePlayerPage_start.setBounds(80, 220, 240, 40);
        singlePlayerPage_back.setBounds(80, 280, 240, 40);
 
    }
 
 
    // multiPlayerPage سنستخدم هذه الدالة لخلق محتوى الصفحة
    private void createMultiPlayerPage() {
 
        // هنا أنشأنا الحاوية الأساسية و الأشياء التي سنضعها فيها
        multiPlayerPage = new JPanel(null);
        multiPlayerPage_firstLabel = new JLabel("Player X");
        multiPlayerPage_secondLabel = new JLabel("Player O");
        multiPlayerPage_firstPlayerName = new JTextField("player 1", 8);
        multiPlayerPage_secondPlayerName = new JTextField("player 2", 8);
        multiPlayerPage_start = new JButton("Start");
        multiPlayerPage_back = new JButton("Back");
 
        // هنا وضعنا كل شيء بداخل الحاوية
        multiPlayerPage.add(multiPlayerPage_firstLabel);
        multiPlayerPage.add(multiPlayerPage_secondLabel);
        multiPlayerPage.add(multiPlayerPage_firstPlayerName);
        multiPlayerPage.add(multiPlayerPage_secondPlayerName);
        multiPlayerPage.add(multiPlayerPage_start);
        multiPlayerPage.add(multiPlayerPage_back);
 
        // هنا قمنا بتحديد حجم و موقع كل شيء أضفناه في الحاوية
        multiPlayerPage_firstLabel.setBounds(80, 130, 70, 30);
        multiPlayerPage_firstPlayerName.setBounds(160, 130, 160, 30);
        multiPlayerPage_secondLabel.setBounds(80, 190, 70, 30);
        multiPlayerPage_secondPlayerName.setBounds(160, 190, 160, 30);
        multiPlayerPage_start.setBounds(80, 250, 240, 40);
        multiPlayerPage_back.setBounds(80, 310, 240, 40);
 
    }
 
 
    // settingsPage سنستخدم هذه الدالة لخلق محتوى الصفحة
    private void createSettingsPage() {
 
        // هنا أنشأنا الحاوية الأساسية و الأشياء التي سنضعها فيها
        settingsPage = new JPanel(null);
        settingsPage_selectedBoardLabel = new JLabel("Game Board");
        settingsPage_selectedBoardValue = new JComboBox(new String[]{"Board 1", "Board 2", "Board 3", "Board 4"});
        settingsPage_selectedFontSizeLabel = new JLabel("Font Size");
        settingsPage_selectedFontSizeValue = new JComboBox(new String[]{"Small", "Meduim", "Large"});
        settingsPage_selectedFontSizeValue.setSelectedIndex(1);
        settingsPage_reset = new JButton("Reset Default Settings");
        settingsPage_back = new JButton("Back");
 
        // هنا وضعنا كل شيء بداخل الحاوية
        settingsPage.add(settingsPage_selectedBoardLabel);
        settingsPage.add(settingsPage_selectedBoardValue);
        settingsPage.add(settingsPage_selectedFontSizeLabel);
        settingsPage.add(settingsPage_selectedFontSizeValue);
        settingsPage.add(settingsPage_reset);
        settingsPage.add(settingsPage_back);
 
        // هنا قمنا بتحديد حجم و موقع كل شيء أضفناه في الحاوية
        settingsPage_selectedBoardLabel.setBounds(80, 130, 100, 30);
        settingsPage_selectedBoardValue.setBounds(200, 130, 120, 30);
        settingsPage_selectedFontSizeLabel.setBounds(80, 190, 100, 30);
        settingsPage_selectedFontSizeValue.setBounds(200, 190, 120, 30);
        settingsPage_reset.setBounds(80, 250, 240, 40);
        settingsPage_back.setBounds(80, 310, 240, 40);
 
    }
 
 
    // gamePage سنستخدم هذه الدالة لخلق محتوى الصفحة
    private void createGamePage() {
 
        // هنا أنشأنا الحاوية الأساسية و الأشياء التي سنضعها فيها
        gamePage = new JPanel(null);
        gamePage_firstPlayerName = new JLabel("", JLabel.CENTER);
        gamePage_secondPlayerName = new JLabel("", JLabel.CENTER);
        gamePage_firstPlayerScore = new JLabel("0", JLabel.CENTER);
        gamePage_secondPlayerScore = new JLabel("0", JLabel.CENTER);
        gamePage_currentPlayerIcon = new JLabel("", JLabel.CENTER);
        gamePage_boardPanel = new JPanel(new GridLayout(3, 3, 8, 8));
        gamePage_boardLabels = new JLabel[9];
        gamePage_back = new JButton("Back");
        gamePage_restart = new JButton("Restart");
        gamePage_boardBackground = new JLabel();
 
        // JLabels التي سنضع فيها 9 gamePage_boardPanel فقط لوضع الصورة خلف الـ Label سنستخدم هذا الـ
        gamePage_boardBackground.setIcon(new ImageIcon(this.getClass().getResource("/images/board_1.png")));
 
        // مع تحديد بعض خصائصهم gamePage_boardPanel في الحاوية JLabels هنا وضعنا الـ 9
        for (int i = 0; i < gamePage_boardLabels.length; i++) {
            gamePage_boardLabels[i] = new JLabel("", JLabel.CENTER);
            gamePage_boardLabels[i].setFont(new Font("Arial", Font.BOLD, 40));
            gamePage_boardLabels[i].setBackground(winnerSquaresBackground);     // Opaque ملحوظة: هذا اللون لن يظهر إلى إذا جعلنا الخلفية صلبة
            gamePage_boardPanel.add(gamePage_boardLabels[i]);
        }
 
        // هنا قمنا بمناداة هذه الدالة لتحديد رمز اللاعب الذي سيلعب الآن على حسب دوره
        setCurrentPlayerIcon();
 
        // هنا وضعنا كل شيء بداخل الحاوية
        gamePage.add(gamePage_firstPlayerName);
        gamePage.add(gamePage_secondPlayerName);
        gamePage.add(gamePage_firstPlayerScore);
        gamePage.add(gamePage_secondPlayerScore);
        gamePage.add(gamePage_currentPlayerIcon);
        gamePage.add(gamePage_boardBackground);
        gamePage.add(gamePage_boardPanel);
        gamePage.add(gamePage_back);
        gamePage.add(gamePage_restart);
 
        // هنا قمنا بتحديد حجم و موقع كل شيء أضفناه في الحاوية
        gamePage_firstPlayerName.setBounds(0, 10, 150, 30);
        gamePage_secondPlayerName.setBounds(250, 10, 150, 30);
        gamePage_firstPlayerScore.setBounds(0, 40, 150, 30);
        gamePage_secondPlayerScore.setBounds(250, 40, 150, 30);
        gamePage_currentPlayerIcon.setBounds(120, 25, 150, 30);
        gamePage_boardBackground.setBounds(45, 105, 300, 300);
        gamePage_boardPanel.setBounds(45, 105, 300, 300);
        gamePage_back.setBounds(20, 475, 140, 30);
        gamePage_restart.setBounds(230, 475, 140, 30);
 
    }
 
 
    // سنستخدم هذه الدالة لإظهار لون خلفية المربعات التي بسببها فاز اللاعب و لإيقاف اللعبة
    private void colorBackgroundWinnerLabels(JLabel l1, JLabel l2, JLabel l3) {
        l1.setOpaque(true);
        l2.setOpaque(true);
        l3.setOpaque(true);
        isGameEnds = true;
    }
 
 
    // سنستخدم هذه الدالة في كل مرة يلعب فيها اللاعبون للتأكد إذا كان هناك فائز أم لا
    // لجعل لون خلفية المربعات التي كانت سبب فوز الاعب ملونة colorBackgroundWinnerLabels في حال كان يوجد فائز سيتم مناداة الدالة
    // لإيقاف اللعبة. و سيتم إضافة واحد في نتيجة اللاعب الفائز true إلى isGameEnds و لتغيير قيمة المتغير
    private void checkIfThereIsAWinner() {
 
        String c0 = gamePage_boardLabels[0].getText();
        String c1 = gamePage_boardLabels[1].getText();
        String c2 = gamePage_boardLabels[2].getText();
        String c3 = gamePage_boardLabels[3].getText();
        String c4 = gamePage_boardLabels[4].getText();
        String c5 = gamePage_boardLabels[5].getText();
        String c6 = gamePage_boardLabels[6].getText();
        String c7 = gamePage_boardLabels[7].getText();
        String c8 = gamePage_boardLabels[8].getText();
 
        int firstPlayerScore = Integer.valueOf(gamePage_firstPlayerScore.getText());
        int secondPlayerScore = Integer.valueOf(gamePage_secondPlayerScore.getText());
 
        if (c0.equals(c1) && c0.equals(c2) && !c0.equals("")) {
            if (c0.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[0], gamePage_boardLabels[1], gamePage_boardLabels[2]);
        }
 
        if (c3.equals(c4) && c3.equals(c5) && !c3.equals("")) {
            if (c3.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[3], gamePage_boardLabels[4], gamePage_boardLabels[5]);
        }
 
        if (c6.equals(c7) && c6.equals(c8) && !c6.equals("")) {
            if (c6.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[6], gamePage_boardLabels[7], gamePage_boardLabels[8]);
        }
 
        if (c0.equals(c3) && c0.equals(c6) && !c0.equals("")) {
            if (c0.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[0], gamePage_boardLabels[3], gamePage_boardLabels[6]);
        }
 
        if (c1.equals(c4) && c1.equals(c7) && !c1.equals("")) {
            if (c1.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[1], gamePage_boardLabels[4], gamePage_boardLabels[7]);
        }
 
        if (c2.equals(c5) && c2.equals(c8) && !c2.equals("")) {
            if (c2.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[2], gamePage_boardLabels[5], gamePage_boardLabels[8]);
        }
 
        if (c0.equals(c4) && c0.equals(c8) && !c0.equals("")) {
            if (c0.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[0], gamePage_boardLabels[4], gamePage_boardLabels[8]);
        }
 
        if (c2.equals(c4) && c2.equals(c6) && !c2.equals("")) {
            if (c2.equals("X"))
                gamePage_firstPlayerScore.setText((firstPlayerScore+1)+"");
            else
                gamePage_secondPlayerScore.setText((secondPlayerScore+1)+"");
            colorBackgroundWinnerLabels(gamePage_boardLabels[2], gamePage_boardLabels[4], gamePage_boardLabels[6]);
        }
 
        gamePage.repaint();
    }
 
 
    // نستخدم هذه الدالة لتحديد دور اللاعب الحالي في حال كان هناك شخصين يلعبان اللعبة
    private boolean isTowPlayerGameEnds(JLabel pressedLabel) {
 
        if (pressedLabel.getText().equals("")) {
 
            if (isFirstPlayerTurn == true) {
                pressedLabel.setText("X");
                pressedLabel.setForeground(xForeground);
                isFirstPlayerTurn = false;
            } else {
                pressedLabel.setText("O");
                pressedLabel.setForeground(oForeground);
                isFirstPlayerTurn = true;
            }
 
            gamePage.repaint();
            checkIfThereIsAWinner();
 
            XOCounter++;
 
            if (XOCounter == 9 || isGameEnds == true) {
                removeXOListener();
                XOCounter = 0;
            }
        }
 
        return isGameEnds;
    }
 
 
    // نستخدم هذه الدالة لتحديد كيف سيلعب الكمبيوتر في حال كان شخص واحد يلعب اللعبة
    private boolean isOnePlayerGameEnds(JLabel pressedLabel) {
 
        if (XOCounter < 9 && pressedLabel.getText().equals("")) {
 
            pressedLabel.setText("X");
            pressedLabel.setForeground(xForeground);
 
            XOCounter++;
 
            repaint();
            checkIfThereIsAWinner();
 
            if (XOCounter < 9 && isGameEnds == false) {
                for (;;) {
                    randomNumber = random.nextInt(9);
                    if (gamePage_boardLabels[randomNumber].getText().equals("")) {
 
                        gamePage_boardLabels[randomNumber].setText("O");
                        gamePage_boardLabels[randomNumber].setForeground(oForeground);
 
                        gamePage.repaint();
 
                        XOCounter++;
                        checkIfThereIsAWinner();
                        break;
                    }
                }
            }
 
        }
 
        if (XOCounter >= 9 || isGameEnds == true) {
            removeXOListener();
            repaint();
            return true;
        }
 
        return false;
 
    }
 
    // غير قابلين للنقر عند إيقاف اللعبة Label نستخدم هذه الدالة لجعل الـ
    private void removeXOListener() {
        for (JLabel gamePage_boardLabel : gamePage_boardLabels) {
            gamePage_boardLabel.removeMouseListener(XOListener);
        }
    }
 
    // سنستخدم هذه الدالة لتحديد رمز اللاعب الذي سيلعب الآن على حسب دوره
    private void setCurrentPlayerIcon() {
        if (isFirstPlayerTurn == true) {
            gamePage_currentPlayerIcon.setText("X");
            gamePage_currentPlayerIcon.setForeground(xForeground);
        }
        else {
            gamePage_currentPlayerIcon.setText("O");
            gamePage_currentPlayerIcon.setForeground(oForeground);
        }
        repaint();
    }
 
 
    // XOListener هنا قمنا بتحديد ما يحدث عندما يقوم المستخدم بالنقر على أزرار الفأرة في الكائن
    MouseListener XOListener = new MouseListener() {
        @Override
        public void mousePressed(MouseEvent e) {
            JLabel pressedLabel = (JLabel) e.getSource();
            if (isGameEnds == false) {
                if (challengeComputer == true)
                    isOnePlayerGameEnds(pressedLabel);
                else if (challengeComputer == false)
                    isTowPlayerGameEnds(pressedLabel);
            }
        }
 
        @Override
        public void mouseClicked(MouseEvent e) { }
 
        @Override
        public void mouseReleased(MouseEvent e) { }
 
        @Override
        public void mouseEntered(MouseEvent e) { }
 
        @Override
        public void mouseExited(MouseEvent e) { }
    };
 
 
    // XOListener نستخدم هذه الدالة عند بدء تحديد جديد لتصفير لوح اللعب و ربط الفأرة بالكائن
    private void startNewGame() {
 
        isGameEnds = false;
        XOCounter = 0;
 
        setCurrentPlayerIcon();
 
        gamePage_boardLabels[0].setOpaque(false);
        gamePage_boardLabels[1].setOpaque(false);
        gamePage_boardLabels[2].setOpaque(false);
        gamePage_boardLabels[3].setOpaque(false);
        gamePage_boardLabels[4].setOpaque(false);
        gamePage_boardLabels[5].setOpaque(false);
        gamePage_boardLabels[6].setOpaque(false);
        gamePage_boardLabels[7].setOpaque(false);
        gamePage_boardLabels[8].setOpaque(false);
 
        gamePage_boardLabels[0].setText("");
        gamePage_boardLabels[1].setText("");
        gamePage_boardLabels[2].setText("");
        gamePage_boardLabels[3].setText("");
        gamePage_boardLabels[4].setText("");
        gamePage_boardLabels[5].setText("");
        gamePage_boardLabels[6].setText("");
        gamePage_boardLabels[7].setText("");
        gamePage_boardLabels[8].setText("");
 
        repaint();
 
        gamePage_boardLabels[0].addMouseListener(XOListener);
        gamePage_boardLabels[1].addMouseListener(XOListener);
        gamePage_boardLabels[2].addMouseListener(XOListener);
        gamePage_boardLabels[3].addMouseListener(XOListener);
        gamePage_boardLabels[4].addMouseListener(XOListener);
        gamePage_boardLabels[5].addMouseListener(XOListener);
        gamePage_boardLabels[6].addMouseListener(XOListener);
        gamePage_boardLabels[7].addMouseListener(XOListener);
        gamePage_boardLabels[8].addMouseListener(XOListener);
 
    }
 
 
    // فقط createAndShowGUI() سيقوم الكونستركتور بإستدعاء الدالة Main عند إنشاء كائن من الكلاس
    public Main() {
        createAndShowGUI();
    }
 
 
    // هذه الدالة تقوم ببناء كل شيء في اللعبة و تحدد ماذا سيحدث عندما يتفاعل المستخدم مع محتوى النافذة
    private void createAndShowGUI() {
 
    // هنا قمن بإستدعاء الدوال التي ستخلق جميع الصفحات في البرنامج
        createStartPage();
        createSinglePlayerPage();
        createMultiPlayerPage();
        createSettingsPage();
        createGamePage();
 
        // لجعل الصفحات موضوعة وراء بعضها البعض CardLayout هنا جعلنا النافذة تستخدم الـ
        CardLayout card = new CardLayout();
        Container container = getContentPane();
        container.setLayout(card);
 
        // هنا أضفنا جميع الصفحات (الحاويات) في النافذة
        add(startPage);
        add(singlePlayerPage);
        add(multiPlayerPage);
        add(settingsPage);
        add(gamePage);
 
        // هنا وضعنا إسم لكل صفحة (حاوية) لنصبح قادرين على تحديد الصفحة التي سيتم عرضها من خلال إسمها
        container.getLayout().addLayoutComponent("startPage", startPage);
        container.getLayout().addLayoutComponent("singlePlayerPage", singlePlayerPage);
        container.getLayout().addLayoutComponent("multiPlayerPage", multiPlayerPage);
        container.getLayout().addLayoutComponent("settingsPage", settingsPage);
        container.getLayout().addLayoutComponent("gamePage", gamePage);
 
        setThemeColors(defaultButtonTextColor, defaultButtonBackgroundColor);
        setNewFont(defaultFont);
 
 
        // لجعلهم قابلين للنقر XOListener بالكائن Labels هنا ربطنا الـ 9
        for (JLabel gamePage_boardLabel : gamePage_boardLabels) {
            gamePage_boardLabel.addMouseListener(XOListener);
        }
 
 
        // تظهر كأول صفحة في النافذة startPage هنا جعلنا الحاوية
        startPage_singlePlayer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                card.show(container, "singlePlayerPage");
            }
        });
 
 
        // ظاهرة multiPlayerPage يجعل الحاوية startPage_multiPlayer هنا جعلنا الزر
        startPage_multiPlayer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            card.show(container, "multiPlayerPage");
            }
        });
 
 
        // ظاهرة settingsPage يجعل الحاوية startPage_settings هنا جعلنا الزر
        startPage_settings.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                card.show(container, "settingsPage");
            }
        });
 
 
        // يعرض نافذة منبثقة فيها بعض المعلومات حول اللعبة startPage_about هنا جعلنا الزر
        startPage_about.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String aboutGame
                        = "<html>"
                        + "<big>TIC TAC TOE</big><br><br>"
                        + "<p>Prepared by a <b>Mhamad Harmush</b><br><br>"
                        + "If you have any comments, ideas.. just let know<br><br>"
                        + "email:   mhamad.harmush@gmail.com<br>"
                        + "twitter & facebook:   @MhamadHarmush<br><br>"
                        + "<u>Note</u><br>"
                        + "I used JDK 1.8 to compile the source code.<br><br><br>"
                        + "<p><i>© Copyright 2017 harmash.com - All Rights Reserved</i></p>"
                        + "<html>";
 
                JOptionPane.showMessageDialog(getContentPane(), aboutGame, "About Tic Tac Toe", JOptionPane.PLAIN_MESSAGE);
            }
        });
 
 
        // يقوم بالخروج من اللعبة startPage_exit هنا جعلنا الزر
        startPage_exit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
 
 
        // للعب ضد الكمبيوتر gamePage يفتح الصفحة singlePlayerPage_start هنا جعلنا الزر
        singlePlayerPage_start.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                gamePage_firstPlayerName.setText("X - " + singlePlayerPage_playerName.getText());
                gamePage_secondPlayerName.setText("O - Computer");
                challengeComputer = true;
                gamePage_firstPlayerScore.setText("0");
                gamePage_secondPlayerScore.setText("0");
                card.show(container, "gamePage");
            }
        });
 
 
        // startPage يعود للصفحة singlePlayerPage_back هنا جعلنا الزر
        singlePlayerPage_back.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                card.show(container, "startPage");
            }
        });
 
 
        // للعب شخصين ضد بعضهما gamePage يفتح الصفحة multiPlayerPage_start هنا جعلنا الزر
        multiPlayerPage_start.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                gamePage_firstPlayerName.setText("X - " + multiPlayerPage_firstPlayerName.getText());
                gamePage_secondPlayerName.setText("O - " + multiPlayerPage_secondPlayerName.getText());
                challengeComputer = false;
                gamePage_firstPlayerScore.setText("0");
                gamePage_secondPlayerScore.setText("0");
                card.show(container, "gamePage");
            }
        });
 
 
        // startPage يعود للصفحة multiPlayerPage_back هنا جعلنا الزر
        multiPlayerPage_back.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                card.show(container, "startPage");
            }
        });
 
 
        // على حسب الصفحة التي كانت مفتوحة multiPlayerPage أو singlePlayerPage يعود للصفحة gamePage_back هنا جعلنا الزر
        gamePage_back.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (challengeComputer == true) {
                    card.show(container, "singlePlayerPage");
                } else {
                    card.show(container, "multiPlayerPage");
                }
                startNewGame();
            }
        });
 
 
        // موجود في على اللوح O و X يزيل أي gamePage_restart هنا جعلنا الزر
        gamePage_restart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startNewGame();
            }
        });
 
 
        // gamePage_boardBackground يجعل المستخدم قادر على تغيير الصورة الموضوعة للـ settingsPage_selectedBoardValue هنا جعلنا الزر
        settingsPage_selectedBoardValue.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
 
                String imageName = "";
 
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    String selectedItem = e.getItem().toString();
 
                    switch (selectedItem) {
                        case "Board 1":
                            imageName = "board_1.png";
                            break;
                        case "Board 2":
                            imageName = "board_2.png";
                            break;
                        case "Board 3":
                            imageName = "board_3.png";
                            break;
                        case "Board 4":
                            imageName = "board_4.png";
                            break;
                    }
                    imageName = "/images/" + imageName;
                    gamePage_boardBackground.setIcon(new ImageIcon(this.getClass().getResource(imageName)));
                    repaint();
                }
            }
        });
 
 
        // يجعل المستخدم قادر على تغيير حجم الخط المستخدم في اللعبة settingsPage_selectedFontSizeValue هنا جعلنا الزر
        settingsPage_selectedFontSizeValue.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
 
                int fontSize = 0;
 
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    String selectedItem = e.getItem().toString();
 
                    switch (selectedItem) {
                        case "Small":
                            fontSize = 15;
                            break;
                        case "Meduim":
                            fontSize = 16;
                            break;
                        case "Large":
                            fontSize = 17;
                            break;
                    }
 
                    setNewFont(new Font("Arial", Font.BOLD, fontSize));
                }
            }
        });
 
 
        // يعيد حجم الخط و صورة اللوح الإفتراضيين settingsPage_reset هنا جعلنا الزر
        settingsPage_reset.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                settingsPage_selectedBoardValue.setSelectedItem("Board 1");
                settingsPage_selectedFontSizeValue.setSelectedItem("Meduim");
                gamePage_boardBackground.setIcon(new ImageIcon(this.getClass().getResource("/images/board_1.png")));
                setNewFont(new Font("Arial", Font.BOLD, 16));
            }
        });
 
 
        // startPage يعود للصفحة multiPlayerPage_back هنا جعلنا الزر
        settingsPage_back.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                card.show(container, "startPage");
            }
        });
 
 
        // هنا قمنا بتحديد بعض خصائص النافذة و جعلناها مرئية
        setTitle("Tic Tac Toe");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 550);
        setLocationRelativeTo(null);
        setResizable(false);
        setVisible(true);
 
 
    }
 
 
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // التي ستنشئ النافذة createAndShowGUI() و بالتالي سيتم إستدعاء الدالة Main هنا قمنا بإنشاء كائن من الكلاس
                new Main();
            }
        });
    }
 
}

هذه الصور جميعها من اللعبة.

java swing tic tac toe source code تحميل كود لعبة tic tac toe في جافا