From eaefb9002ddf570a00c12866e42c8a83aed8112e Mon Sep 17 00:00:00 2001 From: dimasikBurdin <81648493+dimasikBurdin@users.noreply.github.com> Date: Fri, 1 Oct 2021 00:45:54 +0500 Subject: [PATCH] =?UTF-8?q?1-10=20=D0=BF=D1=83=D0=BD=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++---- index.html | 3 + index.js | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++-- styles.css | 10 +++ 4 files changed, 194 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 884044a..4367762 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,15 @@ Сейчас в коде описаны функции для рисования поля любого размера и рисования любого символа в клетке этого поля. Твоя задача дописать код, чтобы это стало полноценной игрой в Крестики-нолики. -1. Реши, как будешь хранить поле. Тебе нужна будет такая структура, в которой удобно понимать есть ли победитель: три клетки по горизонтали, вертикали или диагонали, заполненные одинаковыми символами. -2. Допиши функцию cellClickHandler, чтобы после клика ставился крестик или нолик в соответствующее поле. -3. Если поле, по которому кликнули, не пустое, символ ставиться не должен. -4. Если кончились ходы, выведи alert с текстом "Победила дружба". -5. Напиши функцию, которая считает: есть ли уже победитель. Если есть победитель, выведи alert с названием победителя. -6. Если есть победитель, покрась победные значения в клетках в красный. -7. После победы, клик по полю больше не должен ставить крестик или нолик. -8. Обрабатывай клик по кнопке "Сначала": допиши метод resetClickHandler, чтобы поле очищалось. -9. \* Сделай так, чтобы можно было в начале игры задавать поле произвольного размера. -10. \* Напиши "искусственный интеллект" — функцию, которая будет ставить нолики с случайное пустое поле. -11. \* Напиши чуть более умный искусственный интеллект — функция, ставящая нолики в случайном месте обязана поставить нолик в такое поле, нолик в котором приведет к выигрышу "ИИ". ++++ 1. Реши, как будешь хранить поле. Тебе нужна будет такая структура, в которой удобно понимать есть ли победитель: три клетки по горизонтали, вертикали или диагонали, заполненные одинаковыми символами. ++++ 2. Допиши функцию cellClickHandler, чтобы после клика ставился крестик или нолик в соответствующее поле. ++++ 3. Если поле, по которому кликнули, не пустое, символ ставиться не должен. ++++ 4. Если кончились ходы, выведи alert с текстом "Победила дружба". ++++ 5. Напиши функцию, которая считает: есть ли уже победитель. Если есть победитель, выведи alert с названием победителя. ++++6. Если есть победитель, покрась победные значения в клетках в красный. ++++ 7. После победы, клик по полю больше не должен ставить крестик или нолик. ++++ 8. Обрабатывай клик по кнопке "Сначала": допиши метод resetClickHandler, чтобы поле очищалось. ++++ 9. \* Сделай так, чтобы можно было в начале игры задавать поле произвольного размера. ++++ 10. \* Напиши "искусственный интеллект" — функцию, которая будет ставить нолики в случайное пустое поле. +11. \* Напиши чуть более умный искусственный интеллект — функция, ставящая нолики в случайном месте обязана поставить нолик в такое поле, нолик в котором приведет к выигрышу "ИИ". - таблица всех ходов? 12. \* Сделай так, чтобы при заполнении больше половины клеток на поле, оно бы расширялось: добавлялось бы по одному ряду с каждой стороны. diff --git a/index.html b/index.html index 737a725..c689c6d 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,9 @@ +

Введите размер поля:

+ +
diff --git a/index.js b/index.js index 7553909..db21895 100644 --- a/index.js +++ b/index.js @@ -4,11 +4,26 @@ const EMPTY = ' '; const container = document.getElementById('fieldWrapper'); +let fieldArr = []; +let gameOver = false; +let sizeField = 3; + + +let inputSize = document.querySelector('.input-size'); +let buttonSize = document.querySelector('.input-button'); + +buttonSize.addEventListener('click', () => { + sizeField = inputSize.value; + startGame(); + addResetListener(); + resetClickHandler(); +}) + startGame(); addResetListener(); function startGame () { - renderGrid(3); + renderGrid(sizeField); } function renderGrid (dimension) { @@ -24,16 +39,158 @@ function renderGrid (dimension) { } container.appendChild(row); } + + createDataArr(); +} + +function createDataArr() { + fieldArr = []; + let rows = container.getElementsByTagName('tr'); + for(let i = 0; i < rows.length; i++) { + let col = rows[i].getElementsByTagName('td'); + let temporary = []; + for(let j = 0; j < rows.length; j++) { + temporary.push(col[j]); + } + fieldArr.push(temporary); + } } -function cellClickHandler (row, col) { - // Пиши код тут - console.log(`Clicked on cell: ${row}, ${col}`); +let lastMove = EMPTY; +let move = 1; + +function cellClickHandler(row, col) { + if(gameOver || findCell(row, col).textContent != EMPTY) + return; + console.log(`Clicked on cell: ${row}, ${col}`); - /* Пользоваться методом для размещения символа в клетке так: + if(lastMove == CROSS) { renderSymbolInCell(ZERO, row, col); - */ + fieldArr[row][col].textContent = ZERO; + } else { + renderSymbolInCell(CROSS, row, col); + fieldArr[row][col].textContent = CROSS; + } + lastMove = lastMove == CROSS ? ZERO : CROSS; + + findWinner(); + if(!gameOver){ + checkMove(); + } + + if(lastMove == CROSS) { + setTimeout(() => { + botRandom(); + }, 30); + } +} + +function botRandom() { + + let interval = setInterval(() => { + let row = Math.floor(Math.random() * sizeField); + let col = Math.floor(Math.random() * sizeField); + + if(findCell(row, col).textContent == EMPTY) { + cellClickHandler(row, col); + clearInterval(interval); + } + }, 10); +} + +function findWinner() { + let winner = ""; + + let resRows = ''; + let resColumns = ''; + let resDiagonalRigth = ''; + let resDiagonalLeft = ''; + let resDataRows = []; + let resDataColumns = []; + let resDataDiagonalRigth = []; + let resDataDiagonalLeft = []; + + for(let i = 0; i < fieldArr.length; i++) { + resRows = ''; + resColumns = ''; + resDataRows = []; + resDataColumns = []; + + resDiagonalRigth += fieldArr[i][i].textContent; + resDataDiagonalRigth.push(fieldArr[i][i]); + + resDiagonalLeft += fieldArr[fieldArr.length - 1 - i][i].textContent; + resDataDiagonalLeft.push(fieldArr[fieldArr.length - 1 - i][i]); + + for(let j = 0; j < fieldArr.length; j++) { + resRows += fieldArr[i][j].textContent; + resDataRows.push(fieldArr[i][j]); + + resColumns += fieldArr[j][i].textContent; + resDataColumns.push(fieldArr[j][i]); + } + + winner = chooseWinner(resRows); + if(winner == '') { + winner = chooseWinner(resColumns); + if(winner != '') { + writeWinner(winner, resDataColumns); + return; + } else { + winner = chooseWinner(resDiagonalRigth); + if(winner != '') { + writeWinner(winner, resDataDiagonalRigth); + return; + } else { + winner = chooseWinner(resDiagonalLeft); + if(winner != '') { + writeWinner(winner, resDataDiagonalLeft); + return; + } + } + } + } else { + writeWinner(winner, resDataRows); + return; + } + } +} + +function writeWinner(winner, resData) { + for(let e of resData) { + e.style.color = '#f00'; + } + setTimeout(() => { + alert(`Победил ${winner}`); + }, 10); + gameOver = true; +} + +function chooseWinner(name) { + let winner = ''; + if(name == CROSS.repeat(sizeField)) { + winner = CROSS; + } + else if(name == ZERO.repeat(sizeField)) { + winner = ZERO; + } + return winner; +} + +function checkMove() { + for(let i = 0; i < fieldArr.length; i++) { + for(let j = 0; j < fieldArr.length; j++) { + if(fieldArr[i][j].textContent == EMPTY) { + return; + } + } + } + + setTimeout(() => { + alert('Победила дружба'); + gameOver = true; + }, 10); } function renderSymbolInCell (symbol, row, col, color = '#333') { @@ -54,6 +211,13 @@ function addResetListener () { } function resetClickHandler () { + let rows = container.querySelectorAll('tr'); + for(let elementRow of rows) + for(let cell of elementRow.getElementsByTagName('td')){ + cell.textContent = EMPTY; + } + gameOver = false; + lastMove = EMPTY; console.log('reset!'); } diff --git a/styles.css b/styles.css index c9aaf0b..50aa743 100644 --- a/styles.css +++ b/styles.css @@ -50,4 +50,14 @@ body { font-size: 16px; border: 3px solid orange; border-radius: 5px; +} + +.input-size { + width: 10%; +} + +.input-button { + margin-top: 3%; + width: 70px; + height: 20px; } \ No newline at end of file