Programming Basics SQL HTML CSS JavaScript Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals 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();
}
});
}
}
// 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 في جافا