diff --git a/web/connect-4-game/index.html b/web/connect-4-game/index.html
new file mode 100644
index 0000000..2fb8a1d
--- /dev/null
+++ b/web/connect-4-game/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Connect 4 Game
+
+
+
+
+
Connect 4
+
+
+
+
+
Current Turn: Player 1
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/connect-4-game/script.js b/web/connect-4-game/script.js
new file mode 100644
index 0000000..1d718e5
--- /dev/null
+++ b/web/connect-4-game/script.js
@@ -0,0 +1,315 @@
+const ROWS = 6;
+const COLS = 7;
+let currentPlayer = 1;
+let gameBoard = Array(ROWS).fill().map(() => Array(COLS).fill(0));
+let gameMode = 'player'; // 'player' or 'bot'
+let gameActive = true;
+
+function selectMode(mode) {
+ gameMode = mode;
+ const buttons = document.querySelectorAll('.mode-button');
+ buttons.forEach(btn => btn.classList.remove('selected'));
+ event.target.classList.add('selected');
+ newGame();
+}
+
+function newGame() {
+ gameBoard = Array(ROWS).fill().map(() => Array(COLS).fill(0));
+ currentPlayer = 1;
+ gameActive = true;
+ document.querySelector('.turn-indicator').textContent = 'Current Turn: Player 1';
+ createBoard();
+}
+
+function createBoard() {
+ const board = document.getElementById('board');
+ board.innerHTML = '';
+
+ for (let col = 0; col < COLS; col++) {
+ const column = document.createElement('div');
+ column.className = 'column';
+ column.onclick = () => dropPiece(col);
+
+ for (let row = ROWS - 1; row >= 0; row--) {
+ const cell = document.createElement('div');
+ cell.className = 'cell';
+ cell.dataset.row = row;
+ cell.dataset.col = col;
+ column.appendChild(cell);
+ }
+ board.appendChild(column);
+ }
+}
+
+function dropPiece(col) {
+ if (!gameActive) return;
+
+ // Player's move
+ let row = findLowestEmptyRow(col);
+ if (row === -1) return; // Column is full
+
+ gameBoard[row][col] = currentPlayer;
+ updateBoard();
+
+ if (checkWin(row, col)) {
+ document.querySelector('.turn-indicator').textContent = `Player ${currentPlayer} wins!`;
+ gameActive = false;
+ return;
+ }
+
+ if (checkDraw()) {
+ document.querySelector('.turn-indicator').textContent = "It's a draw!";
+ gameActive = false;
+ return;
+ }
+
+ currentPlayer = currentPlayer === 1 ? 2 : 1;
+ document.querySelector('.turn-indicator').textContent = `Current Turn: Player ${currentPlayer}`;
+
+ // Bot's move
+ if (gameMode === 'bot' && currentPlayer === 2 && gameActive) {
+ setTimeout(() => {
+ const botCol = getBotMove();
+ dropPiece(botCol);
+ }, 500);
+ }
+}
+
+function findLowestEmptyRow(col) {
+ for (let row = 0; row < ROWS; row++) {
+ if (gameBoard[row][col] === 0) {
+ return row;
+ }
+ }
+ return -1;
+}
+
+function checkDraw() {
+ return gameBoard.every(row => row.every(cell => cell !== 0));
+}
+
+function getBotMove() {
+ // Create a copy of the board for simulation
+ function copyBoard() {
+ return gameBoard.map(row => [...row]);
+ }
+
+ // Evaluate a position (higher score is better for bot)
+ function evaluatePosition(board, row, col, player) {
+ let score = 0;
+ const directions = [
+ [0, 1], // horizontal
+ [1, 0], // vertical
+ [1, 1], // diagonal /
+ [1, -1] // diagonal \
+ ];
+
+ for (let [dx, dy] of directions) {
+ // Count pieces in both directions
+ let count = 1;
+ let spaces = 0;
+ let blocked = false;
+
+ // Check in positive direction
+ for (let i = 1; i < 4; i++) {
+ const newRow = row + dx * i;
+ const newCol = col + dy * i;
+
+ if (newRow < 0 || newRow >= ROWS || newCol < 0 || newCol >= COLS) {
+ blocked = true;
+ break;
+ }
+
+ if (board[newRow][newCol] === player) {
+ count++;
+ } else if (board[newRow][newCol] === 0) {
+ spaces++;
+ break;
+ } else {
+ blocked = true;
+ break;
+ }
+ }
+
+ // Check in negative direction
+ for (let i = 1; i < 4; i++) {
+ const newRow = row - dx * i;
+ const newCol = col - dy * i;
+
+ if (newRow < 0 || newRow >= ROWS || newCol < 0 || newCol >= COLS) {
+ blocked = true;
+ break;
+ }
+
+ if (board[newRow][newCol] === player) {
+ count++;
+ } else if (board[newRow][newCol] === 0) {
+ spaces++;
+ break;
+ } else {
+ blocked = true;
+ break;
+ }
+ }
+
+ // Score based on the sequence
+ if (count >= 4) return 100000; // Winning move
+ if (count === 3 && spaces >= 1 && !blocked) score += 100; // Potential win
+ if (count === 2 && spaces >= 2 && !blocked) score += 10; // Building sequence
+ }
+
+ // Bonus for center columns
+ score += Math.max(0, 3 - Math.abs(3 - col)) * 2;
+
+ return score;
+ }
+
+ // Try each column and evaluate the resulting position
+ const moveScores = [];
+ for (let col = 0; col < COLS; col++) {
+ const row = findLowestEmptyRow(col);
+ if (row === -1) {
+ moveScores.push(-1000000); // Invalid move
+ continue;
+ }
+
+ let score = 0;
+ const boardCopy = copyBoard();
+
+ // Check immediate win
+ boardCopy[row][col] = 2;
+ if (checkWin(row, col)) {
+ return col; // Winning move, take it immediately
+ }
+
+ // Check if opponent wins next move
+ let opponentWinNext = false;
+ for (let oppCol = 0; oppCol < COLS; oppCol++) {
+ const oppRow = findLowestEmptyRow(oppCol);
+ if (oppRow !== -1) {
+ boardCopy[oppRow][oppCol] = 1;
+ if (checkWin(oppRow, oppCol)) {
+ opponentWinNext = true;
+ if (col === oppCol) {
+ score += 80; // Block opponent's winning move
+ }
+ }
+ boardCopy[oppRow][oppCol] = 0;
+ }
+ }
+
+ // Evaluate the position
+ score += evaluatePosition(boardCopy, row, col, 2); // Evaluate for bot
+ score -= evaluatePosition(boardCopy, row, col, 1); // Consider opponent's position
+
+ // Add some randomness to make the bot less predictable
+ score += Math.random() * 5;
+
+ moveScores.push(score);
+ }
+
+ // Choose the move with the highest score
+ let bestScore = -1000000;
+ let bestMoves = [];
+
+ for (let col = 0; col < COLS; col++) {
+ if (moveScores[col] > bestScore) {
+ bestScore = moveScores[col];
+ bestMoves = [col];
+ } else if (moveScores[col] === bestScore) {
+ bestMoves.push(col);
+ }
+ }
+
+ // Randomly choose from equally good moves
+ return bestMoves[Math.floor(Math.random() * bestMoves.length)];
+}
+
+function updateBoard() {
+ for (let row = 0; row < ROWS; row++) {
+ for (let col = 0; col < COLS; col++) {
+ const cell = document.querySelector(
+ `[data-row="${row}"][data-col="${col}"]`
+ );
+ cell.className = 'cell';
+ if (gameBoard[row][col] === 1) cell.classList.add('red');
+ if (gameBoard[row][col] === 2) cell.classList.add('yellow');
+ }
+ }
+}
+
+function checkWin(row, col) {
+ const directions = [
+ [[0, 1], [0, -1]], // horizontal
+ [[1, 0], [-1, 0]], // vertical
+ [[1, 1], [-1, -1]], // diagonal
+ [[1, -1], [-1, 1]] // other diagonal
+ ];
+
+ for (let dir of directions) {
+ const winningCells = [[row, col]];
+ let count = 1;
+
+ // Check both directions
+ for (let [deltaRow, deltaCol] of dir) {
+ let r = row + deltaRow;
+ let c = col + deltaCol;
+
+ while (
+ r >= 0 && r < ROWS &&
+ c >= 0 && c < COLS &&
+ gameBoard[r][c] === currentPlayer
+ ) {
+ winningCells.push([r, c]);
+ count++;
+ r += deltaRow;
+ c += deltaCol;
+ }
+ }
+
+ if (count >= 4) {
+ // Highlight winning cells
+ winningCells.forEach(([r, c]) => {
+ const cell = document.querySelector(
+ `[data-row="${r}"][data-col="${c}"]`
+ );
+ cell.classList.add('winner');
+ });
+ return true;
+ }
+ }
+ return false;
+}
+
+function countDirection(row, col, deltaRow, deltaCol) {
+ let count = 0;
+ let r = row + deltaRow;
+ let c = col + deltaCol;
+
+ while (
+ r >= 0 && r < ROWS &&
+ c >= 0 && c < COLS &&
+ gameBoard[r][c] === currentPlayer
+ ) {
+ count++;
+ r += deltaRow;
+ c += deltaCol;
+ }
+ return count;
+}
+
+function resetGame() {
+ gameBoard = Array(ROWS).fill().map(() => Array(COLS).fill(0));
+ currentPlayer = 1;
+ gameActive = true;
+ document.querySelector('.turn-indicator').textContent =
+ 'Current Turn: Player 1';
+ // Remove winner class from all cells
+ document.querySelectorAll('.cell.winner').forEach(cell => {
+ cell.classList.remove('winner');
+ });
+ updateBoard();
+}
+
+// Initialize the game
+createBoard();
\ No newline at end of file
diff --git a/web/connect-4-game/style.css b/web/connect-4-game/style.css
new file mode 100644
index 0000000..c5a7558
--- /dev/null
+++ b/web/connect-4-game/style.css
@@ -0,0 +1,238 @@
+@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');
+
+:root {
+ --board-bg: #4a90e2;
+ --cell-bg: #f0f4f8;
+ --player1-color: #ff5a5f;
+ --player2-color: #ffc947;
+ --text-color: #333;
+ --bg-color: #f7f9fc;
+ --white: #ffffff;
+ --shadow-light: rgba(0, 0, 0, 0.05);
+ --shadow-dark: rgba(0, 0, 0, 0.15);
+}
+
+body {
+ margin: 0;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ background-color: var(--bg-color);
+ font-family: 'Poppins', sans-serif;
+ color: var(--text-color);
+}
+
+#game-container {
+ background: var(--white);
+ padding: 2rem;
+ border-radius: 20px;
+ box-shadow: 0 10px 40px var(--shadow-light);
+ text-align: center;
+ max-width: 90%;
+}
+
+h1 {
+ color: var(--text-color);
+ text-align: center;
+ margin-bottom: 1.5rem;
+ font-weight: 700;
+ font-size: 2.5rem;
+}
+
+.turn-indicator {
+ color: var(--text-color);
+ text-align: center;
+ margin-bottom: 1.5rem;
+ font-size: 1.1rem;
+ font-weight: 600;
+ padding: 0.75rem 1rem;
+ background: var(--cell-bg);
+ border-radius: 12px;
+ display: inline-block;
+}
+
+.game-board {
+ display: flex;
+ gap: 8px;
+ background: var(--board-bg);
+ padding: 15px;
+ border-radius: 15px;
+ box-shadow: inset 0 4px 10px var(--shadow-dark);
+}
+
+.column {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+ border-radius: 10px;
+}
+
+.column:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+}
+
+.cell {
+ width: 60px;
+ height: 60px;
+ background: var(--cell-bg);
+ border-radius: 50%;
+ transition: background-color 0.4s ease, transform 0.3s ease;
+ box-shadow: inset 0 3px 6px var(--shadow-dark);
+}
+
+.cell.red, .cell.yellow {
+ animation: dropPiece 0.4s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards;
+ box-shadow: none;
+}
+
+.cell.red {
+ background-image: radial-gradient(circle at top left, #ff8a80, var(--player1-color));
+}
+
+.cell.yellow {
+ background-image: radial-gradient(circle at top left, #ffd166, var(--player2-color));
+}
+
+.cell.winner {
+ animation: winPulse 0.8s ease-in-out infinite;
+}
+
+@keyframes winPulse {
+ 0% {
+ transform: scale(1);
+ box-shadow: 0 0 0 0px rgba(255, 255, 255, 0.7);
+ }
+ 100% {
+ transform: scale(1.15);
+ box-shadow: 0 0 0 15px rgba(255, 255, 255, 0);
+ }
+}
+
+@keyframes dropPiece {
+ 0% {
+ transform: translateY(-400px) scale(0.8);
+ opacity: 0;
+ }
+ 100% {
+ transform: translateY(0) scale(1);
+ opacity: 1;
+ }
+}
+
+#mode-selection {
+ display: flex;
+ justify-content: center;
+ gap: 0.75rem;
+ margin-bottom: 1.5rem;
+}
+
+.mode-button {
+ padding: 0.6rem 1.2rem;
+ font-size: 0.9rem;
+ font-weight: 600;
+ background: var(--cell-bg);
+ color: var(--text-color);
+ border: 2px solid var(--cell-bg);
+ border-radius: 10px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.mode-button:hover {
+ background: #e1e8f0;
+ transform: translateY(-2px);
+}
+
+.mode-button.selected {
+ background: var(--board-bg);
+ border-color: var(--board-bg);
+ color: var(--white);
+ box-shadow: 0 4px 10px rgba(74, 144, 226, 0.4);
+}
+
+.button-container {
+ display: flex;
+ justify-content: center;
+ gap: 1.5rem;
+ margin-top: 1.5rem;
+}
+
+.reset-button, .new-game-button {
+ padding: 0.9rem 2rem;
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--white);
+ border: none;
+ border-radius: 12px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ box-shadow: 0 5px 15px var(--shadow-dark);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.reset-button {
+ background: var(--player1-color);
+}
+
+.new-game-button {
+ background: #28a745;
+}
+
+.reset-button:hover, .new-game-button:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 20px var(--shadow-dark);
+}
+
+.reset-button:hover {
+ background: #e04a4f;
+}
+
+.new-game-button:hover {
+ background: #218838;
+}
+
+.reset-button:active, .new-game-button:active {
+ transform: translateY(0);
+ box-shadow: 0 2px 5px var(--shadow-dark);
+}
+
+@media (max-width: 768px) {
+ .cell {
+ width: 45px;
+ height: 45px;
+ }
+
+ #game-container {
+ padding: 1rem;
+ }
+
+ h1 {
+ font-size: 2rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .cell {
+ width: 38px;
+ height: 38px;
+ }
+
+ .game-board {
+ padding: 10px;
+ gap: 5px;
+ }
+
+ .column {
+ gap: 5px;
+ }
+
+ .button-container {
+ flex-direction: column;
+ gap: 0.75rem;
+ }
+}
\ No newline at end of file