├── favicon.ico
├── src
├── images
│ ├── desktop.png
│ └── mobile.png
├── css
│ └── style.css
└── js
│ └── script.js
├── index.html
└── README.md
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/javascript-xo-game/HEAD/favicon.ico
--------------------------------------------------------------------------------
/src/images/desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/javascript-xo-game/HEAD/src/images/desktop.png
--------------------------------------------------------------------------------
/src/images/mobile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/javascript-xo-game/HEAD/src/images/mobile.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | X O Game
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | display: flex;
5 | align-items: center;
6 | justify-content: center;
7 | min-height: 100vh;
8 | background-color: #f0f4f8;
9 | font-family: 'Arial', sans-serif;
10 | flex-direction: column;
11 | box-sizing: border-box;
12 | }
13 |
14 | .board {
15 | display: grid;
16 | grid-template-columns: repeat(3, 1fr);
17 | grid-template-rows: repeat(3, 1fr);
18 | gap: 8px;
19 | max-width: 350px;
20 | max-height: 350px;
21 | width: 100%;
22 | height: 100vh;
23 | background-color: #fff;
24 | padding: 10px;
25 | border-radius: 15px;
26 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
27 | }
28 |
29 | .cell {
30 | width: 100%;
31 | height: 100%;
32 | display: flex;
33 | align-items: center;
34 | justify-content: center;
35 | font-size: 36px;
36 | font-weight: bold;
37 | color: #333;
38 | background-color: #f9f9f9;
39 | border: 1px solid #ddd;
40 | border-radius: 8px;
41 | cursor: pointer;
42 | transition: background-color 0.3s, transform 0.3s ease, box-shadow 0.3s ease;
43 | }
44 |
45 | .cell:hover {
46 | background-color: #e0e0e0;
47 | transform: scale(1.1);
48 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
49 | }
50 |
51 | #game-board {
52 | background-color: #f4f4f9;
53 | padding: 20px;
54 | border-radius: 15px;
55 | box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
56 | margin-bottom: 20px;
57 | }
58 |
59 | #game-over-message {
60 | font-size: 20px;
61 | font-weight: bold;
62 | color: #333;
63 | margin-top: 15px;
64 | text-align: center;
65 | display: none;
66 | }
67 |
68 | #restart-button {
69 | margin-top: 20px;
70 | padding: 12px 18px;
71 | font-size: 18px;
72 | font-weight: 600;
73 | cursor: pointer;
74 | background-color: #4caf50;
75 | color: #fff;
76 | border: none;
77 | border-radius: 8px;
78 | transition: background-color 0.3s, transform 0.3s ease;
79 | }
80 |
81 | #restart-button:hover {
82 | background-color: #45a049;
83 | transform: scale(1.05);
84 | }
85 |
86 | @media screen and (max-width: 600px) {
87 | .board {
88 | max-width: 90%;
89 | grid-template-columns: repeat(3, 1fr);
90 | grid-template-rows: repeat(3, 1fr);
91 | }
92 |
93 | #game-board {
94 | padding: 15px;
95 | }
96 |
97 | #game-over-message {
98 | font-size: 18px;
99 | }
100 |
101 | #restart-button {
102 | font-size: 16px;
103 | padding: 10px 15px;
104 | }
105 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🎮 JavaScript XO Game
2 |
3 | This is a **Tic-Tac-Toe (XO) game** implemented using **HTML, CSS, and JavaScript**. The game allows **two players** to compete on a **3x3 grid**.
4 |
5 | ## 👀 Preview
6 |
7 | ### 💻 **Desktop**
8 | 
9 |
10 | ### 📱 **Mobile**
11 | 
12 |
13 | ## 🚀 Features
14 |
15 | - ✅ **Responsive Design:** The game adapts to **all screen sizes**.
16 | - 🎮 **Interactive Game Board:** Players can **place X or O** by clicking on cells.
17 | - 🏆 **Winner Highlight:** The **winning combination** is highlighted in **green**.
18 | - 🤝 **Draw Detection:** If the game ends in a draw, a **message is displayed**.
19 | - 🔄 **Play Again Button:** A **restart button** allows players to reset the game and play again.
20 |
21 | ## 🛠️ Installation
22 |
23 | To set up and run the XO Game on your local machine:
24 |
25 | ### 1️⃣ **Clone the Repository**
26 | ```bash
27 | git clone https://github.com/Iqbolshoh/javascript-xo-game.git
28 | ```
29 | ### 2️⃣ **Navigate to the Project Directory**
30 | ```bash
31 | cd javascript-xo-game
32 | ```
33 | ### 3️⃣ **Open the `index.html` File**
34 | Simply open the `index.html` file in any modern **web browser** to start playing.
35 |
36 | ## 🖥 Technologies Used
37 | 
38 | 
39 | 
40 |
41 | ## 📜 License
42 | This project is open-source and available under the **MIT License**.
43 |
44 | ## 🤝 Contributing
45 | 🎯 Contributions are welcome! If you have suggestions or want to enhance the project, feel free to fork the repository and submit a pull request.
46 |
47 | ## 📬 Connect with Me
48 | 💬 I love meeting new people and discussing tech, business, and creative ideas. Let’s connect! You can reach me on these platforms:
49 |
50 |
110 |
--------------------------------------------------------------------------------
/src/js/script.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", function () {
2 | const board = document.getElementById("game-board");
3 | const gameOverMessage = document.getElementById("game-over-message");
4 | const restartButton = document.getElementById("restart-button");
5 | let currentPlayer = "X";
6 | let gameOver = false;
7 |
8 | function createCell() {
9 | const cell = document.createElement("div");
10 | cell.classList.add("cell");
11 | cell.addEventListener("click", handleCellClick);
12 | return cell;
13 | }
14 |
15 | function handleCellClick(event) {
16 | if (gameOver || event.target.textContent !== "" || currentPlayer !== "X") {
17 | return;
18 | }
19 |
20 | event.target.textContent = currentPlayer;
21 |
22 | if (checkWinner()) {
23 | gameOverMessage.textContent = `${currentPlayer} wins!`;
24 | gameOverMessage.style.display = "block";
25 | gameOver = true;
26 | animateWinner();
27 | restartButton.style.display = "block";
28 | return;
29 | } else {
30 | currentPlayer = "O";
31 | }
32 |
33 | if (checkDraw()) {
34 | gameOverMessage.textContent = "It's a draw!";
35 | gameOverMessage.style.display = "block";
36 | gameOver = true;
37 | restartButton.style.display = "block";
38 | } else if (!gameOver) {
39 | setTimeout(computerMove, 500);
40 | }
41 | }
42 |
43 | function computerMove() {
44 | const cells = document.querySelectorAll(".cell");
45 | let availableCells = [];
46 |
47 | cells.forEach((cell, index) => {
48 | if (cell.textContent === "") {
49 | availableCells.push(cell);
50 | }
51 | });
52 |
53 | if (availableCells.length > 0) {
54 | const bestMove = findBestMove();
55 | bestMove.textContent = "O";
56 |
57 | if (checkWinner()) {
58 | gameOverMessage.textContent = "O wins!";
59 | gameOverMessage.style.display = "block";
60 | gameOver = true;
61 | animateWinner();
62 | restartButton.style.display = "block";
63 | } else {
64 | currentPlayer = "X";
65 | }
66 |
67 | if (checkDraw() && !gameOver) {
68 | gameOverMessage.textContent = "It's a draw!";
69 | gameOverMessage.style.display = "block";
70 | gameOver = true;
71 | restartButton.style.display = "block";
72 | }
73 | }
74 | }
75 |
76 | function checkWinner() {
77 | const cells = document.querySelectorAll(".cell");
78 |
79 | const winCombinations = [
80 | [0, 1, 2], [3, 4, 5], [6, 7, 8],
81 | [0, 3, 6], [1, 4, 7], [2, 5, 8],
82 | [0, 4, 8], [2, 4, 6]
83 | ];
84 |
85 | for (const combo of winCombinations) {
86 | const [a, b, c] = combo;
87 | if (cells[a].textContent && cells[a].textContent === cells[b].textContent && cells[b].textContent === cells[c].textContent) {
88 | highlightWinner(cells[a], cells[b], cells[c]);
89 | return true;
90 | }
91 | }
92 |
93 | return false;
94 | }
95 |
96 | function highlightWinner(cellA, cellB, cellC) {
97 | cellA.style.backgroundColor = "#8bc34a";
98 | cellB.style.backgroundColor = "#8bc34a";
99 | cellC.style.backgroundColor = "#8bc34a";
100 | }
101 |
102 | function animateWinner() {
103 | const winningCells = document.querySelectorAll(".cell[style='background-color: #8bc34a;']");
104 |
105 | winningCells.forEach(cell => {
106 | cell.style.transition = "transform 0.5s ease-in-out";
107 | cell.style.transform = "scale(1.2)";
108 | });
109 | }
110 |
111 | function checkDraw() {
112 | const cells = document.querySelectorAll(".cell");
113 | for (const cell of cells) {
114 | if (cell.textContent === "") {
115 | return false;
116 | }
117 | }
118 | return true;
119 | }
120 |
121 | function findBestMove() {
122 | const cells = document.querySelectorAll(".cell");
123 |
124 | const winCombinations = [
125 | [0, 1, 2], [3, 4, 5], [6, 7, 8],
126 | [0, 3, 6], [1, 4, 7], [2, 5, 8],
127 | [0, 4, 8], [2, 4, 6]
128 | ];
129 |
130 | for (const combo of winCombinations) {
131 | const [a, b, c] = combo;
132 | const combination = [cells[a], cells[b], cells[c]];
133 |
134 | if (combination.filter(cell => cell.textContent === "O").length === 2 && combination.some(cell => cell.textContent === "")) {
135 | return combination.find(cell => cell.textContent === "");
136 | }
137 |
138 | if (combination.filter(cell => cell.textContent === "X").length === 2 && combination.some(cell => cell.textContent === "")) {
139 | return combination.find(cell => cell.textContent === "");
140 | }
141 | }
142 |
143 | const center = cells[4];
144 | if (center.textContent === "") {
145 | return center;
146 | }
147 |
148 | const availableCells = Array.from(cells).filter(cell => cell.textContent === "");
149 | return availableCells[Math.floor(Math.random() * availableCells.length)];
150 | }
151 |
152 | restartButton.addEventListener("click", function () {
153 | location.reload();
154 | });
155 |
156 | for (let i = 0; i < 9; i++) {
157 | board.appendChild(createCell());
158 | }
159 | });
--------------------------------------------------------------------------------