Змейка. Говно-код
Здравствуйте. Нужен совет. Как сделать подобие ООП? На данный момент навоял следующее:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title></title> <style> html, body { margin: 0; padding: 0; height: 100%; } body { display: flex; align-items: center; justify-content: center; flex-direction: column; } table { border: 1px solid #00bfff; border-collapse: collapse; } td { border: 1px solid #00bfff; width: 10px; height: 10px; } </style> </head> <body> <script> let snake = []; const field = document.createElement('table'); let tr, td; let timerID; let direction = 'ArrowRight'; let prev; let eaten; let score = 0; let generated; let reverseDirections = { 'ArrowRight': 'ArrowLeft', 'ArrowLeft': 'ArrowRight', 'ArrowUp': 'ArrowDown', 'ArrowDown': 'ArrowUp' }; let snakeInitWidth = 3; let snakeInitHeight = 1; let scoreElem = `<section id="score">Score: <span>0</span></section>`; document.body.insertAdjacentHTML('afterbegin', scoreElem); let fieldWidth = 41; let fieldHeight = 21; for (let i = 0; i < fieldHeight; i++) { tr = document.createElement('tr'); for (let j = 0; j < fieldWidth; j++) { td = document.createElement('td'); if (i == (fieldHeight - snakeInitHeight) / 2 && j >= (fieldWidth - snakeInitWidth) / 2 && j < (fieldWidth - snakeInitWidth) / 2 + snakeInitWidth) { snake.unshift({x: j, y: i}); td.style.backgroundColor = '#00bfff' } tr.append(td); } field.append(tr); } document.body.append(field); let fieldX = fieldWidth - 1; let fieldY = fieldHeight - 1; document.addEventListener('keydown', function(e) { if (e.code == 'ArrowRight' || e.code == 'ArrowLeft' || e.code == 'ArrowUp' || e.code == 'ArrowDown') { if (e.code != direction && direction != reverseDirections[e.code]) { direction = e.code; if (timerID) clearTimeout(timerID) move(e.code); } } }); function move(keyName) { if (checkLoss()) { clearTimeout(timerID); blink(); return; } for (let i = 0; i < snake.length; i++) { field.rows[snake[i].y].cells[snake[i].x].style.backgroundColor = ''; if (i == 0) { prev = Object.assign({}, snake[i]); if (keyName == 'ArrowUp') { if (snake[i].y - 1 >= 0 && field.rows[snake[i].y - 1].cells[snake[i].x].style.backgroundColor == 'black' || snake[i].y - 1 < 0 && field.rows[fieldY].cells[snake[i].x].style.backgroundColor == 'black') { eaten = true; } snake[i].y = (snake[i].y == 0) ? fieldY : snake[i].y - 1; } if (keyName == 'ArrowDown') { if (snake[i].y + 1 <= fieldY && field.rows[snake[i].y + 1].cells[snake[i].x].style.backgroundColor == 'black' || snake[i].y + 1 > fieldY && field.rows[0].cells[snake[i].x].style.backgroundColor == 'black') { eaten = true; } snake[i].y = (snake[i].y == fieldY) ? 0 : snake[i].y + 1; } if (keyName == 'ArrowRight') { if (snake[i].x + 1 <= fieldX && field.rows[snake[i].y].cells[snake[i].x + 1].style.backgroundColor == 'black' || snake[i].x + 1 > fieldX && field.rows[snake[i].y].cells[0].style.backgroundColor == 'black') { eaten = true; } snake[i].x = (snake[i].x == fieldX) ? 0 : snake[i].x + 1; } if (keyName == 'ArrowLeft') { if (snake[i].x - 1 >= 0 && field.rows[snake[i].y].cells[snake[i].x - 1].style.backgroundColor == 'black' || snake[i].x - 1 < 0 && field.rows[snake[i].y].cells[fieldX].style.backgroundColor == 'black') { eaten = true; } snake[i].x = (snake[i].x == 0) ? fieldX : snake[i].x - 1; } if (eaten) { score += 10; document.querySelector('#score > span').innerHTML = score; let lastCell = Object.assign({}, prev); snake.splice(1, 0, lastCell); field.rows[prev.y].cells[prev.x].style.backgroundColor = '#00bfff'; eaten = false; generateFood(); i = 0; continue; } } else { let temp = snake[i]; snake[i] = prev; prev = temp; } field.rows[snake[i].y].cells[snake[i].x].style.backgroundColor = '#00bfff'; } timerID = setTimeout(() => move(keyName), 100); } move('ArrowRight'); function checkLoss() { for (let i = 1; i < snake.length; i++) { if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) return true; } return false; } function blink() { debugger; let count = 0; function tick() { if (count == 6) return; for (let i = 0; i < snake.length; i++) { if (count % 2 == 0) { field.rows[snake[i].y].cells[snake[i].x].style.backgroundColor = ''; } else { field.rows[snake[i].y].cells[snake[i].x].style.backgroundColor = '#00bfff'; } } count++; setTimeout(tick, 500); } tick(); } function generateFood() { let emptyCells = Array.from(field.querySelectorAll('td')).filter((td) => td.style.backgroundColor == ''); generated = Math.floor(Math.random() * emptyCells.length); emptyCells[generated].style.backgroundColor = 'black'; } generateFood(); </script> </body> </html> Думаю сделать два класса - Field и Snake. Класс Field будет создавать поле для игры, генерировать еду и некоторые другие методы. Класс Snake будет отвечать за создание, движение змейки. Или здесь ООП вообще не уместно? |
ООП уместно - это о связности кода, потому что у вас сейчас перемешано все.
Вот можете посмотреть мою реализацию. Как минимум, чтобы отделить бизнес логику игры и работу с "представлением" - html, события |
micscr,
спасибо за ответ. Ознакомлюсь с вашей реализацией. |
Rise,
спасибо, интересный подход. |
Часовой пояс GMT +3, время: 16:23. |