Змейка. Говно-код 
		
		
		
		Здравствуйте. Нужен совет. Как сделать подобие ООП? На данный момент навоял следующее: 
	
<!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, время: 02:52. |