Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<div id="0_8"></div>
<div id="0_9"></div>
</div>

<div id="scores" class="scores">0</div>

<div class="line">
<div id="1_0"></div>
<div id="1_1"></div>
Expand Down
130 changes: 107 additions & 23 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
/* Задание
*
* 1. Добавить управление
* 2. Каждая из сторон при пресечении должна перемещать на противоположенную
* 3. Добавить рандомное появление еды (подсказка: надо навешивать на ячейки класс food)
* 4. Размер змейки должен увеличиваться
* 5*. Научиться увеличивать сокрость игры при увеличении количества очков
* 1. Добавить управление +
* 2. Каждая из сторон при пресечении должна перемещать на противоположенную +
* 3. Добавить рандомное появление еды (подсказка: надо навешивать на ячейки класс food) +
* 3,5. Добавить поедание змейкой еды. +
* 4. Размер змейки должен увеличиваться
* 5*. Научиться увеличивать сокрость игры при увеличении количества очков
* 6**. Придумать новую фичу и реализовать
*
*/

var snakeGame = (function () {
var snakeGame = (function() {
//Константы оформляются в особом стиле
const WIDTH = 10;
const HEIGHT = 10;

let isFoodEaten = true;
let scores = 0;

let headX = 0;
let headY = 0;
let dx = 1;
Expand All @@ -23,19 +27,61 @@ var snakeGame = (function () {
let playStep = () => {
headX += dx;
headY += dy;
checkCoords(headX, headY);
let newHeadCell = getCell(headX, headY);

removeSnakeCells();
addSnakeToCell(newHeadCell);
removeSnakeCells();

checkForFood(newHeadCell);
addObjToCell(newHeadCell, " snake");
setCellStep(newHeadCell, currentStep);

if (isFoodEaten) {
refreshScore(scores);
spawnFood();
isFoodEaten = false;
}

currentStep++;
return true;
}

let getScore = () => {
return scores;
}

let checkForFood = headCell => {
if (isFood(headCell)) {
removeObjFromCell(headCell, "food");
isFoodEaten = true;
scores++;
}
}

//При пересечении стороны перемещает на противоположную
let checkCoords = (hX, hY) => {
if (hX >= WIDTH) {
headX = 0;
}
if (hX < 0) {
headX = WIDTH - 1;
}
if (hY >= HEIGHT) {
headY = 0;
}
if (hY < 0) {
headY = HEIGHT - 1;
}
}

let removeSnakeCells = () => {
for (let snakeCell of getSnakeCells())
removeSnakeFromCell(snakeCell);
removeObjFromCell(snakeCell, "snake");
}

let isFood = cell => {
//indexOf возвращает -1, если входжений строки нет
return cell.className.indexOf("food") != -1;
}

let getCell = (x, y) => {
Expand All @@ -48,47 +94,85 @@ var snakeGame = (function () {
return document.getElementsByClassName('snake');
}

let addSnakeToCell = cell => {
let addObjToCell = (cell, obj) => {
// Строчка className может включать несколько классов, например "class1 class2".
// Поэтому добавляем пробел.
cell.className += ' snake';
cell.className += ' ' + obj;
}

let removeSnakeFromCell = cell => {
cell.className = cell.className.replace('snake', '');
let removeObjFromCell = (cell, obj) => {
cell.className = cell.className.replace(obj, '');
}

let setCellStep = (cell, step) => {
// Есть соглашение, что пользовательские атрибуты называются с префикса "data-".
cell.setAttribute('data-step', step);
}

let getCellStep = cell => {
let getCellStep = cell => {
// Явное преобразование строки к числу через объект-обертку.
return new Number(cell.getAttribute('data-step'));
}

let setDirection = (x, y) => {
//Меняет направление, если аргументами не передается противоположное текущему
dx = (x == -dx) ? dx : x;
dy = (y == -dy) ? dy : y;
}

let getRandomNumber = (min, max) => {
return Math.random() * (max - min) + min;
}

let spawnFood = () => {
let x = Math.round(getRandomNumber(0, WIDTH - 1));
let y = Math.round(getRandomNumber(0, HEIGHT - 1));

let foodCell = getCell(x, y);
addObjToCell(foodCell, " food");
}

// Только этот объект будет доступен извне.
return {
getScore: 0,
playStep: playStep
getScore: getScore,
playStep: playStep,
setDirection: setDirection
}
})(); // Используем IIFE (Immediately Invoked Function Expression) для изоляции.

// Главный цикл игры.
let timer = setInterval(function () {
if (!snakeGame.playStep())
{
let timer = setInterval(function() {
if (!snakeGame.playStep()) {
// Игра закончена - останавливаем цикл.
clearInterval(timer);
alert('Game Over! Score: ' + snakeGame.getScore());
}
}, 500);
}, 300);


let refreshScore = scores => {
let scoreDiv = document.getElementById('scores');
scoreDiv.innerHTML = scores;
}

// Обработка действий пользователя.
document.onkeydown = e => {
switch (e.keyCode)
{
// http://keycode.info/
switch (e.keyCode) {
//w
case (87):
snakeGame.setDirection(0, -1);
break;
//a
case (65):
snakeGame.setDirection(-1, 0);
break;
//s
case (83):
snakeGame.setDirection(0, 1);
break;
//d
case (68):
snakeGame.setDirection(1, 0);
break;
}
}
14 changes: 14 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@
transition: background-color .5s;
}

.main div.scores {
width: 40px;
height: 20px;
float: left;
margin: 1px;
border: 1px solid green;
border-radius: 4px;
background-color: #fff;
text-align: right;
color: #666;
font-family: sans-serif;
font-weight: bold;
}

.main .line div.food {
background-color: green;
transition: background-color 2s;
Expand Down