diff --git a/index.html b/index.html index 737a725..69ce380 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + Крестики-нолики @@ -8,14 +8,12 @@
- - - +
- + - \ No newline at end of file + diff --git a/index.js b/index.js index 7553909..03bcc0a 100644 --- a/index.js +++ b/index.js @@ -3,22 +3,37 @@ const ZERO = 'O'; const EMPTY = ' '; const container = document.getElementById('fieldWrapper'); +const resetButton = document.getElementById('reset'); + +let board = []; +let currentPlayer = CROSS; +let gameActive = true; +let size = 3; startGame(); addResetListener(); -function startGame () { - renderGrid(3); +function startGame() { + let inputSize = prompt("Введите размер поля (минимум 3):", "3"); + size = parseInt(inputSize); + if (isNaN(size) || size < 3) { + size = 3; + } + gameActive = true; + currentPlayer = CROSS; + board = Array(size).fill(null).map(() => Array(size).fill(EMPTY)); + renderGrid(size); } -function renderGrid (dimension) { +function renderGrid(dimension) { container.innerHTML = ''; - for (let i = 0; i < dimension; i++) { const row = document.createElement('tr'); for (let j = 0; j < dimension; j++) { const cell = document.createElement('td'); - cell.textContent = EMPTY; + cell.textContent = board[i][j]; + cell.dataset.row = i; + cell.dataset.col = j; cell.addEventListener('click', () => cellClickHandler(i, j)); row.appendChild(cell); } @@ -26,64 +41,179 @@ function renderGrid (dimension) { } } -function cellClickHandler (row, col) { - // Пиши код тут - console.log(`Clicked on cell: ${row}, ${col}`); +function cellClickHandler(row, col) { + if (!gameActive || board[row][col] !== EMPTY) return; + board[row][col] = currentPlayer; + renderSymbolInCell(currentPlayer, row, col); - /* Пользоваться методом для размещения символа в клетке так: - renderSymbolInCell(ZERO, row, col); - */ + if (checkWinner(currentPlayer)) { + gameActive = false; + alert(`Победитель: ${currentPlayer}`); + return; + } + + if (board.flat().every(cell => cell !== EMPTY)) { + alert("Победила дружба!"); + gameActive = false; + return; + } + + checkExpandBoard(); + + currentPlayer = currentPlayer === CROSS ? ZERO : CROSS; + if (currentPlayer === ZERO && gameActive) { + setTimeout(aiMove, 100); + } } -function renderSymbolInCell (symbol, row, col, color = '#333') { +function renderSymbolInCell(symbol, row, col, color = '#333') { const targetCell = findCell(row, col); - targetCell.textContent = symbol; targetCell.style.color = color; } -function findCell (row, col) { - const targetRow = container.querySelectorAll('tr')[row]; - return targetRow.querySelectorAll('td')[col]; +function findCell(row, col) { + return container.querySelectorAll('tr')[row].querySelectorAll('td')[col]; } -function addResetListener () { - const resetButton = document.getElementById('reset'); +function addResetListener() { resetButton.addEventListener('click', resetClickHandler); } -function resetClickHandler () { - console.log('reset!'); +function resetClickHandler() { + startGame(); } +function checkWinner(player, doHighlight = true) { + for (let i = 0; i < size; i++) { + if (board[i].every(cell => cell === player)) { + if (doHighlight) highlightWinner(i, 'row'); + return true; + } + if (board.map(row => row[i]).every(cell => cell === player)) { + if (doHighlight) highlightWinner(i, 'col'); + return true; + } + } + + if (board.map((row, i) => row[i]).every(cell => cell === player)) { + if (doHighlight) highlightWinner(0, 'diag1'); + return true; + } + + if (board.map((row, i) => row[size - 1 - i]).every(cell => cell === player)) { + if (doHighlight) highlightWinner(0, 'diag2'); + return true; + } -/* Test Function */ -/* Победа первого игрока */ -function testWin () { - clickOnCell(0, 2); - clickOnCell(0, 0); - clickOnCell(2, 0); - clickOnCell(1, 1); - clickOnCell(2, 2); - clickOnCell(1, 2); - clickOnCell(2, 1); + return false; } -/* Ничья */ -function testDraw () { - clickOnCell(2, 0); - clickOnCell(1, 0); - clickOnCell(1, 1); - clickOnCell(0, 0); - clickOnCell(1, 2); - clickOnCell(1, 2); - clickOnCell(0, 2); - clickOnCell(0, 1); - clickOnCell(2, 1); - clickOnCell(2, 2); +function highlightWinner(index, type) { + if (type === 'row') { + for (let j = 0; j < size; j++) { + renderSymbolInCell(board[index][j], index, j, 'red'); + } + } else if (type === 'col') { + for (let i = 0; i < size; i++) { + renderSymbolInCell(board[i][index], i, index, 'red'); + } + } else if (type === 'diag1') { + for (let i = 0; i < size; i++) { + renderSymbolInCell(board[i][i], i, i, 'red'); + } + } else if (type === 'diag2') { + for (let i = 0; i < size; i++) { + renderSymbolInCell(board[i][size - 1 - i], i, size - 1 - i, 'red'); + } + } } -function clickOnCell (row, col) { - findCell(row, col).click(); +function checkWinnerOnBoard(testBoard, player) { + const n = testBoard.length; + for (let i = 0; i < n; i++) { + if (testBoard[i].every(cell => cell === player)) return true; + if (testBoard.map(row => row[i]).every(cell => cell === player)) return true; + } + if (testBoard.map((row, i) => row[i]).every(cell => cell === player)) return true; + if (testBoard.map((row, i) => row[n - 1 - i]).every(cell => cell === player)) return true; + return false; +} + +function aiMove() { + if (!gameActive) return; + let moveMade = false; + + for (let i = 0; i < size; i++) { + for (let j = 0; j < size; j++) { + if (board[i][j] === EMPTY) { + let boardClone = board.map(row => row.slice()); + boardClone[i][j] = ZERO; + if (checkWinnerOnBoard(boardClone, ZERO)) { + board[i][j] = ZERO; + renderSymbolInCell(ZERO, i, j, 'blue'); + moveMade = true; + if (checkWinner(ZERO)) { + gameActive = false; + alert(`Победитель: ${ZERO}`); + } + break; + } + } + } + if (moveMade) break; + } + + if (!moveMade) { + let emptyCells = []; + for (let i = 0; i < size; i++) { + for (let j = 0; j < size; j++) { + if (board[i][j] === EMPTY) { + emptyCells.push({ i, j }); + } + } + } + if (emptyCells.length > 0) { + let randomIndex = Math.floor(Math.random() * emptyCells.length); + let cell = emptyCells[randomIndex]; + board[cell.i][cell.j] = ZERO; + renderSymbolInCell(ZERO, cell.i, cell.j, 'blue'); + if (checkWinner(ZERO)) { + gameActive = false; + alert(`Победитель: ${ZERO}`); + } + } + } + + if (board.flat().every(cell => cell !== EMPTY)) { + alert("Победила дружба!"); + gameActive = false; + } + + checkExpandBoard(); + currentPlayer = CROSS; +} + +function checkExpandBoard() { + let filledCount = board.flat().filter(cell => cell !== EMPTY).length; + let totalCells = size * size; + if (filledCount > totalCells / 2) { + expandBoard(); + } +} + +function expandBoard() { + let oldSize = size; + let newSize = oldSize + 2; + let newBoard = Array(newSize).fill(null).map(() => Array(newSize).fill(EMPTY)); + + for (let i = 0; i < oldSize; i++) { + for (let j = 0; j < oldSize; j++) { + newBoard[i + 1][j + 1] = board[i][j]; + } + } + board = newBoard; + size = newSize; + renderGrid(size); }