Показать сообщение отдельно
  #1 (permalink)  
Старый 14.04.2022, 13:17
Аватар для micscr
Профессор
Отправить личное сообщение для micscr Посмотреть профиль Найти все сообщения от micscr
 
Регистрация: 10.09.2009
Сообщений: 1,577

Обсуждение структуры скрипта с ООП
Приветствую.
Пока без всяких сборщиков, фреймворков и реактивных вещей, старый добрый скрипт, делаю чтобы с использованием объектов и кое какой структурой типа MVC.
Только C тут не стал делать.
Модель отвечает за данные и алгоритмы.
А Вьюха - за html и события.
Главное чтобы не лапшекод перемешанный, а с разделением ответственности.
Вроде наглядно получилось, ваше мнение по улучшению?
Вы таким бы способом делали, если на объектах ( а не просто процедурно)?

Реализация игры "Пятнашки":

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<style>
		td {
			border: 2px solid black;
			width: 20px;
			height: 20px;
			text-align: center;
		}
	</style>	
	<script
			  src="https://code.jquery.com/jquery-3.6.0.min.js"
			  integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
			  crossorigin="anonymous"></script>
	<script>
$(document).ready(function(){
	'use strict';

	let model = new Model();
	let view = new View(model, '#tablefield', '#result', '#process');

	
	function View(model, tablefieldId, resultId, startGameButton) {
		this.model = model;
		this.$tablefield = $(tablefieldId);
		this.$result = $(resultId);
		this.$startGameButton = $(startGameButton);
		
		let _view = this;

		this.$startGameButton.click(function(){
			if (!_view.model.getIsGameOver()) {
				_view.$result.html('Игра уже идет').show().fadeOut(2000);
				return;
			}
			_view.model.startGame();
			_view.showTable();
			_view.initializeTable();
			$(this).prop('disabled', true);
		});
		
		this.showTable = function () {
			let table = this.model.table;
			this.$tablefield.html('');
			let res = '<table>';
			for (let i = 0; i < table.length; i++){
				res += '<tr>';
				for (let j = 0; j < table[i].length; j++){
					let cell = table[i][j];
					res += '<td style="' + '' + '">';
					res += cell;
					res += '</td>';
				}				
				res += '</tr>';
			}		
			res += '</table>';
			
			this.$tablefield.html(res);
			this.$result.html('Игра начинается, соберите числа от 1 до 15 по рядам сверху вниз').show().fadeOut(4000);
		}		

		this.initializeTable = function (){
			$('td').click(function(){
				let model = _view.model;
				if (model.getIsGameOver()) {
					_view.$result.html('Игра завершена, начните новую игру').show().fadeOut(2000);
					return;
				}				
				let $td = $(this);
				if ($td.html() == '') {
					_view.$result.html('Пустую ячейку нельзя перемещать').show().fadeOut(2000);
					return;
				}
				let $tr = $td.parent();
				let $table = $tr.parent();
				let x = $td.prevAll().length;
				let y = $tr.prevAll().length;
				if (model.getIsMoveOk(x, y)) {
					let coord = model.getEmptyCellCoordinates();					
					let $emptyTd = $table.children().eq(coord.y).children().eq(coord.x);
					let val = $td.html();					
					model.makeMove(x, y);
					$emptyTd.html(val);
					$td.html('');
					if (model.getIsSuccess()) {
						_view.$result.html('ВЫ УСПЕШНО СОБРАЛИ ПАЗЛ. ПОЗДРАВЛЯЕМ !!!').show();
						model.isGameOver = true;
						_view.$startGameButton.prop('disabled', false);
					}
				} else {
					_view.$result.html('Ход не корректен, выберите ячейку рядом с пустой').show().fadeOut(2000);
				}
				
			});	
		}		
	}
	
	function Model() {
		this.isGameOver = true;
		this.table = [];
		
		this.getIsGameOver = function(){
			return this.isGameOver;
		}
		
		this.startGame = function(){
			this.isGameOver = false;
			this.table = [];
			let numbers = [];
			while (numbers.length < 16) {
				let num = this.getRandomNumber(0, 15);
				if (numbers.indexOf(num) === -1) {
					numbers.push(num);
				}
			}
			// для демо игры
			//numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,0,14,15];
			for (let i = 0; i < 4; i++){
				this.table.push([]);
				for (let j = 0; j < 4; j++){
					let el = numbers.shift();
					this.table[i].push(el ? el : '');
				}		
			}
			//console.log(this.table);
		}
		
		this.getIsMoveOk = function(x, y){
			let coord = this.getEmptyCellCoordinates();
			return (Math.abs(coord.x - x) + Math.abs(coord.y - y)) == 1
		}
		
		this.makeMove = function(x, y){
			let coord = this.getEmptyCellCoordinates();
			let val = this.table[y][x];
			this.table[y][x] = '';
			this.table[coord.y][coord.x] = val;	
			//console.log(this.table);			
		}		
		
		this.getEmptyCellCoordinates = function() {
			for (let i = 0; i < this.table.length; i++){
				for (let j = 0; j < this.table[i].length; j++){
					if (!this.table[i][j]) {
						return {
							x: j,
							y: i,
						};
					}
				}
			}
		}		
		
		this.getIsSuccess = function() {
			let start = 0;
			for (let i = 0; i < this.table.length; i++){
				for (let j = 0; j < this.table[i].length; j++){
					start++;
					if (start <= 15 && start != this.table[i][j]) {
						return false;
					}
				}
			}
			return true;
		}		
		
		this.getRandomNumber = function(min, max){
			let delta = Math.floor(max - min + 1); 
			let num = Math.random() * delta;
			return min + Math.floor(num);
		};
		
	}
	
		
});


	</script>
	
</head>
<body >
<button id="process">Начать игру</button>
<div id="tablefield">
</div>
<div id="result" style="color:red;">
	
</div>

</body>
</html>
Ответить с цитированием