class Connect4Game { constructor(container) { this.tableContainer = document.querySelector(container); this.reset(); this.tableContainer.addEventListener("click", (e) => this.playerMove(e)); } reset() { this.turn = 0; this.board = Array(6).fill().map(() => Array(7).fill(0)); this.render(); } set(column) { if (column >= 0 && column < 7) { for (let i = 5; i >= 0; i--) { if (this.board[i][column] === 0) { this.board[i][column] = this.turn + 1; console.log(`Player ${this.turn + 1} placed at (${i}, ${column})`); this.turn ^= 1; return i; } } console.log(`Player ${this.turn + 1} could not place, column ${column} full`); return false; } } render(win = null) { this.tableContainer.innerHTML = ''; if (win) { const winText = document.createTextNode(`Player ${win[0][0]} won. Click on the board to reset the game.`); this.tableContainer.appendChild(winText); } const table = document.createElement("table"); for (let i = 0; i < 6; i++) { const row = document.createElement("tr"); for (let j = 0; j < 7; j++) { const cell = document.createElement("td"); if (win && win.some(([_, x, y]) => x === i && y === j)) { const player = win.find(([_, x, y]) => x === i && y === j)[0]; cell.classList.add(`winning${player}`); } if (this.board[i][j] === 1) { cell.classList.add("player1"); } else if (this.board[i][j] === 2) { cell.classList.add("player2"); } row.appendChild(cell); } table.appendChild(row); } this.tableContainer.appendChild(table); } playerMove(e) { if (this.turn === -1 || this.turn === -2) { this.reset(); } else { const column = e.target.cellIndex; this.set(column); const result = this.checkWin(); if (result) { this.turn = (result[0][0]) * -1; } this.render(result); } } checkColumns() { for (let j = 0; j < 7; j++) { let ctr = 0; let winningCells = []; for (let i = 0; i < 6; i++) { if (this.board[i][j] !== 0 && this.board[i][j] === this.board[i + 1]?.[j]) { ctr++; winningCells.push([this.board[i][j], i, j]); } else { ctr = 0; winningCells = []; } if (ctr === 3) { winningCells.push([this.board[i + 1][j], i + 1, j]); return winningCells; } } } return null; } checkRows() { for (let i = 0; i < 6; i++) { let ctr = 0; let winningCells = []; for (let j = 0; j < 7; j++) { if (this.board[i][j] !== 0 && this.board[i][j] === this.board[i][j + 1]) { ctr++; winningCells.push([this.board[i][j], i, j]); } else { ctr = 0; winningCells = []; } if (ctr === 3) { winningCells.push([this.board[i][j + 1], i, j + 1]); return winningCells; } } } return null; } checkDescendingDiagonals() { for (let i = 0; i < 3; i++) { for (let j = 0; j < 4; j++) { let player = this.board[i][j]; if (player !== 0 && player === this.board[i + 1][j + 1] && player === this.board[i + 2][j + 2] && player === this.board[i + 3][j + 3]) { return [ [player, i, j], [player, i + 1, j + 1], [player, i + 2, j + 2], [player, i + 3, j + 3] ]; } } } return null; } checkAscendingDiagonals() { for (let i = 0; i < 3; i++) { for (let j = 3; j < 7; j++) { let player = this.board[i][j]; if (player !== 0 && player === this.board[i + 1][j - 1] && player === this.board[i + 2][j - 2] && player === this.board[i + 3][j - 3]) { return [ [player, i, j], [player, i + 1, j - 1], [player, i + 2, j - 2], [player, i + 3, j - 3] ]; } } } return null; } checkWin() { let winArray = []; let columnWin = this.checkColumns(); if (columnWin) { winArray = winArray.concat(columnWin); } let rowWin = this.checkRows(); if (rowWin) { winArray = winArray.concat(rowWin); } let descendingDiagonalWin = this.checkDescendingDiagonals(); if (descendingDiagonalWin) { winArray = winArray.concat(descendingDiagonalWin); } let ascendingDiagonalWin = this.checkAscendingDiagonals(); if (ascendingDiagonalWin) { winArray = winArray.concat(ascendingDiagonalWin); } return winArray.length > 0 ? winArray : null; } } const game = new Connect4Game("#table-container"); const game2 = new Connect4Game("#table-container2");