В этом модуле вы шаг за шагом создадите работающую игру «Крестики-нолики», используя манипуляции с DOM. Задания построены логически: от генерации игрового поля и обработки кликов до реализации игровой логики (смена игрока, проверка победы) и функции перезапуска игры. Вам предстоит работать с методами поиска элементов, созданием узлов, событиями и свойствами содержимого элементов. Итоговый результат будет полностью функциональной мини-игрой.
- Модуль 1: Основы выбора элементов
- Выбор элемента по ID.
- Выбор элементов по классу.
- Выбор элементов по тегу.
- Выбор по селектору CSS.
- Выбор по атрибуту.
- Поиск элементов внутри другого элемента.
- Поиск родительского элемента.
- Поиск соседних элементов (предыдущий, следующий).
- Поиск первого и последнего дочернего элемента.
- Поиск всех дочерних элементов.
- Модуль 2: Манипуляция содержимым
- Модуль 3: Работа с атрибутами
- Модуль 4: Управление классами
- Модуль 5: Управление стилями
- Модуль 6: Создание и удаление элементов
- Создание нового элемента.
- Вставка элемента перед другим элементом.
- Вставка элемента после другого элемента.
- Добавление элемента в определенную позицию внутри списка дочерних элементов.
- Удаление элемента из DOM.
- Замена одного элемента другим.
- Перемещение существующего элемента в другое место DOM..
- Очистка содержимого элемента без его удаления.
- Модуль 7: Обработка событий
- Модуль 8: Работа с формами
- Модуль 9: Продвинутые манипуляции
- Модуль 10: Работа с размерами и прокруткой
- Получение размеров элемента.
- Получение позиции элемента относительно окна браузера.
- Получение позиции элемента относительно родительского элемента.
- Управление прокруткой страницы.
- Определение, виден ли элемент в текущей области просмотра.
- Плавная прокрутка к элементу.
- Создание элемента, который фиксируется при прокрутке.
- Модуль 11: Работа с медиа-элементами
- Модуль 12: Практические задания
Генерация игрового поля
Для начала нам нужно создать сетку игры 3x3. У нас есть пустой контейнер. Ваша задача — с помощью цикла создать 9 элементов `div`, добавить каждому класс `cell` и поместить их внутрь игрового поля.
.board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; width: 150px; margin: 0 auto; } .cell { width: 50px; height: 50px; background: #eee; display: flex; align-items: center; justify-content: center; font-size: 24px; cursor: pointer; border: 1px solid #ccc; }
<div id="game-board" class="board"></div>
const board = document.getElementById("game-board");
for (let i = 0; i < 9; i++) {
const cell = document.input__1("div");
cell.input__2 = "cell";
board.input__3(cell);
}
Обработка клика по ячейке
Поле создано. Теперь нужно научить ячейки реагировать на нажатия. Найдите все элементы с классом `.cell` и добавьте каждому обработчик события клика, который будет выводить в консоль текст 'Click'.
.board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; width: 150px; margin: 0 auto; } .cell { width: 50px; height: 50px; background: #eee; border: 1px solid #ccc; cursor: pointer; }
<div class="board"><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div></div>
const cells = document.input__1(".cell");
cells.forEach(cell => {
cell.input__2("input__3", function() {
console.log("Click");
});
});
Отображение хода (Крестик)
При клике мы должны узнать, на какой именно элемент нажали, и записать в него символ 'X'. Используйте объект события для доступа к целевому элементу.
.board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; width: 150px; margin: 0 auto; } .cell { width: 50px; height: 50px; background: #eee; display: flex; align-items: center; justify-content: center; font-size: 24px; border: 1px solid #ccc; cursor: pointer; }
<div class="board"><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div></div>
const cells = document.querySelectorAll(".cell");
cells.forEach(cell => {
cell.addEventListener("click", function(event) {
const targetCell = event.input__1;
targetCell.input__2 = "X";
});
});
Смена игрока
Игра не может состоять только из крестиков. Реализуйте логику смены игрока: если текущий игрок 'X', то следующим должен стать 'O', и наоборот. Заполните пропуски в тернарном операторе.
.status { margin-bottom: 10px; font-weight: bold; }
<div id="status" class="status">Ходит: X</div>
let currentPlayer = "X";
const statusDisplay = document.getElementById("status");
function changePlayer() {
currentPlayer = currentPlayer === "X" ? "input__1" : "input__2";
statusDisplay.textContent = "Ходит: " + currentPlayer;
}
// Эмуляция вызова для проверки
changePlayer();
Проверка занятости ячейки
Сейчас можно нажать на уже заполненную ячейку и перезаписать значение. Это неправильно. Добавьте условие: если в ячейке уже есть текст (не пустая строка), то мы выходим из функции и ничего не делаем.
.cell { width: 50px; height: 50px; background: #eee; border: 1px solid #ccc; display: flex; align-items: center; justify-content: center; }
<div class="cell">X</div>
const cell = document.querySelector(".cell");
function handleCellClick(clickedCell) {
// Проверяем, занята ли ячейка
if (clickedCell.input__1 !== "") {
return;
}
console.log("Ход выполнен");
}
handleCellClick(cell);
Логика победы: Проверка комбинации
Самая сложная часть — определить победителя. У нас есть массив выигрышных комбинаций (индексы ячеек). Вам нужно внутри цикла проверки сравнить значения трех ячеек, входящих в комбинацию. Если они равны и не пусты — это победа.
.board { display: none; }
<div class="board"></div>
const cells = [/*...массив 9 элементов...*/];
// Представим, что cells уже заполнен элементами DOM
const winningConditions = [
[0, 1, 2], [3, 4, 5], [6, 7, 8] // и другие...
];
function checkResult() {
let roundWon = false;
for (let i = 0; i < winningConditions.length; i++) {
const winCondition = winningConditions[i];
let a = cells[winCondition[0]].textContent;
let b = cells[winCondition[1]].textContent;
let c = cells[winCondition[2]].textContent;
if (a === "" || b === "" || c === "") {
continue;
}
if (a === input__1 && b === input__2) {
roundWon = true;
break;
}
}
return roundWon;
}
Визуализация победы
Если игрок победил, давайте выделим выигрышную комбинацию цветом. Вам нужно добавить класс `winner` элементам, которые составили линию победы.
.board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; width: 150px; margin: 0 auto; } .cell { width: 50px; height: 50px; background: #eee; display: flex; align-items: center; justify-content: center; border: 1px solid #ccc; } .winner { background-color: #90ee90; }
<div class="board"><div class="cell">X</div><div class="cell">X</div><div class="cell">X</div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div></div>
const cells = document.querySelectorAll(".cell");
const winCondition = [0, 1, 2]; // Индексы победившей строки
// Добавляем класс winner победным ячейкам
cells[winCondition[0]].input__1.add("winner");
cells[winCondition[1]].input__1.add("winner");
cells[winCondition[2]].input__1.add("input__2");
Кнопка перезапуска игры
Игра закончилась, нужно начать заново. Напишите функцию очистки поля. Она должна пройтись по всем ячейкам и очистить их текстовое содержимое.
.cell { width: 50px; height: 50px; background: #eee; border: 1px solid #ccc; margin: 2px; display: inline-block;} button { margin-top: 10px; }
<div><div class="cell">X</div><div class="cell">O</div><div class="cell">X</div></div><button id="restart">Заново</button>
const cells = document.querySelectorAll(".cell");
const restartBtn = document.getElementById("restart");
restartBtn.addEventListener("click", function() {
cells.forEach(cell => {
cell.input__1 = "";
cell.classList.input__2("winner"); // на всякий случай убираем класс победы
});
});