Pull to refresh

Ход конем с использованием canvas

Reading time6 min
Views8.2K
image
Посмотреть.

Работая в одной из компаний, где мало понимают в программирование и сайтостроение, а основной список задач сводиться к тому, что необходимо залить новость на корпоративный сайт, мне иногда приходят от начальства списки интересных задач. Об эффективности и необходимости вносить их на сайт спорить бесполезно, с высоты высокого гнезда начальство не слышит доводы разума, приходиться браться за ненужные никому проекты и выполнять их.

Одно из такой задач стала — Ход конем. Суть ее в том, что необходимо найти маршрут шахматного коня, проходящего через все поля доски по одному разу. Реализовать задачу решил с использованием canvas, немного jQuery, с учетом в будущем сделать плагин.

Постараюсь описать все логику своих действий. По началу было много идей в голове, немного покопался в поисковиках и в который раз убедившись, что все же лучше написать самому, да и в целом будет полезно для развития и закрепления знаний, приступил к работе с мыслью, что главное начать, а там пойдет.

В общем сама html разметка довольна проста.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Ход конем</title>
	<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
    <div class="chess">
    	<canvas id="chess">Updet!</canvas>         
    </div>
    	<div class="info">
        	<p>Количество шагов: 1<p>
            <p>Количество ошибок: 0<p>
        </div>
</body>
	<script src="js/jQuery.js"></script>
	<script src="js/script.js"></script>
</html>


Стили тоже просты, единственное что стоить отметить — это картинка шахматной доски решил залить через background.

* {
	margin: 0px;
	padding: 0px;
}
body,
html {
	height: 100%;
}
.chess {
	margin: auto;
	position: relative;
	width: 600px;
	height: 600px;
}
.chess canvas {
	margin: 28px 0 0 58px;
	background: url(../images/chess-block.png) no-repeat;
}
.kon {
	position: absolute;
	width: 52px;
	height: 98px;
	background: url(../images/kon.png) no-repeat;
}


Далее по коду уже только javaScript, создаем функцию инициализации init, которая будет создать объект canvas. Создаем 3 глобальных элемента (2 из которых массива), что в общем не очень хорошо, но все же реализация тестовая и главная работает. Значение которые принимает функция init есть начальный и затем последующий точки координат шахматного коня, х и у соответственно отвечают координатам по оси х и по оси x. При первом вызове они не определенны (undefined), поэтому приравниваем им начальные значения, в нашем случае это 60(x) и 480(y) что равно правому нижнему углу шахматной доски(A1).

Далее в массив arr вносим координаты текущего положения коня, это позволить нам запомнить все ходы коня, чтобы в будущем на них уже нельзя было ходить.

Далее создаем сам canvas, затем определяем потенциальные ходы, делаем это исходя из позиций коня на шахматной доске. Сама клетка ровна 60px, отсюда и выражения типа [x+60*2, y+60], то есть на две клетки вверху и одну клетку в правый бок, как мы знаем, конь ходит буквой «Г». Все варианты записываем в массив v1, затем перебираем возможные варианты ходов и в каждой нашей потенциальной клетке создаем объект с помощью функций rect.

Благодаря все тоже же функции rect создаем объект в клетки где уже побывал конь.

var ctx; var arr=[];var v1=[]; var error=0;

function rect(color, x, y, width, height,opecity) {
    this.color = color; // цвет прямоугольника
    this.x = x; // координата х
    this.y = y; // координата у
    this.width = width; // ширина
    this.height = height; // высота
    this.draw = function() // Метод рисующий прямоугольник
    {
		ctx.beginPath();
		ctx.globalAlpha = opecity;
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.width, this.height);
    }
	this.clear = function(){
		ctx.clearRect(this.x, this.y, this.width, this.height);
	}
}

function init(p,h){
	(p===undefined) ? x=60 : x=p;
	(h===undefined) ? y=480 : y=h;
		//дефолтный 1 - вариант.
		if (x < 60 ) x = 60;if (x > 480 ) x = 480;
		if (y < 60 ) y = 60;if (y > 480 ) y = 480;
	//запоминаем значение для ошибок 
	arr.push([x,y]);
	//рисуем, сам канвас
	var chess = document.getElementById("chess");
	var width = chess.width = 600;
	var height = chess.height = 600;
	ctx = chess.getContext('2d');
	ctx.clearRect(0,0,width,height);
	
//определяем потенциальные ходы (создаем массив элементов) всего 8 вариантов
	v1 = [
		[x+60*2, y+60],
		[x+60*2, y-60],
		[x+60, y+60*2],
		[x-60, y+60*2],
		[x+60, y-60*2],
		[x-60, y-60*2],
		[x-60*2, y-60],
		[x-60*2, y+60]
	];
// закрашиваем их 
	
	for(var v=0;v<v1.length;v++){
		if(v1[v][0]>59 && v1[v][0]<481 && v1[v][1]>59 && v1[v][1]<481) 		{
			var f = new rect('#ffe800',v1[v][0],v1[v][1],60,60,0.4);
				f.draw();
		}
	}
//закрашиваем то, откуда пришел конь
for (var i=0;i<arr.length;i++) {
		var f = new rect('#f00',arr[i][0],arr[i][1],60,60,1);
				f.draw();
}
	//рисуем коня
	imkago(x,y);
}
init();


В самом конце мы вызываем функцию imkago(x,y), которая создает коня на шахматной доске. Она достаточно проста, создаем картинку и вставляем ее в canvas. Позиция коня принимается от функций инициализации init.


function imkago(x,y) {
	var kon = new Image();
	kon.src = 'images/kon.png';
	kon.onload = function() {
		ctx.beginPath();
		ctx.globalAlpha = 1;
		ctx.drawImage(kon, x+3, y-45);	
	}
}


Последнее что нужно было сделать, это дать возможность двигать коня, причем только по правилам шахмат, то есть буквой «Г», при этом запретить возможность ходить по клеткам, на которых уже побывал конь.

Сначала получаем позицию клика. Путем нехитрых математический действий получаем точные координаты на шахматной доске. (x = (Math.floor(x/60))*60 и y = (Math.floor(y/60))*60).

Затем сравниваем с помощью цикла for (var j=0;j<arr.length;j++) наличие в массиве с клетками где побывал конь с координатами клетки, которые мы получили при клике. если они ровны возвращаем false.

Последнее сравниваем полученные координаты при клике с массивом потенциальных ходов, если они совпадают, вызываем функцию init с новыми координатами для коня.

 $('#chess').click(function(event){
 var x = event.pageX - this.offsetLeft-$('.chess').offset().left;
 var y = event.pageY - this.offsetTop;
	  	x = (Math.floor(x/60))*60;
		y = (Math.floor(y/60))*60;
//сравниваем, если нет совпадений. ничего не происходить, смотрим ошибки
		for (var j=0;j<arr.length;j++) {
			if (arr[j][0]==x && arr[j][1]==y){
				error++;
				$(".info").html("<p>Количество шагов: "+arr.length+"<p><p>Количество ошибок: "+error+"<p>");
				return false;
			}	
		}
	for(var v=0;v<v1.length;v++){	
			if(v1[v][0]==x && v1[v][1]==y) {
					init(x,y);
			}
	}
	$(".info").html("<p>Количество шагов: "+arr.length+"<p><p>Количество ошибок: "+error+"<p>");
})


Код javaScript полностью
javaScript
var ctx; var arr=[];var v1=[]; var error=0;
function rect(color, x, y, width, height,opecity) {
    this.color = color; // цвет прямоугольника
    this.x = x; // координата х
    this.y = y; // координата у
    this.width = width; // ширина
    this.height = height; // высота
    this.draw = function() // Метод рисующий прямоугольник
    {
		ctx.beginPath();
		ctx.globalAlpha = opecity;
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.width, this.height);
    }
	this.clear = function(){
		ctx.clearRect(this.x, this.y, this.width, this.height);
	}
}
function init(p,h){
	(p===undefined) ? x=60 : x=p;
	(h===undefined) ? y=480 : y=h;
		//дефолтный 1 - вариант.
		if (x < 60 ) x = 60;if (x > 480 ) x = 480;
		if (y < 60 ) y = 60;if (y > 480 ) y = 480;
	//запоминаем значение для ошибок 
	arr.push([x,y]);
	//рисуем, сам канвас
	var chess = document.getElementById("chess");
	var width = chess.width = 600;
	var height = chess.height = 600;
	ctx = chess.getContext('2d');
	ctx.clearRect(0,0,width,height);
	
//определяем потенциальные ходы (создаем массив элементов) всего 8 вариантов
	v1 = [
		[x+60*2, y+60],
		[x+60*2, y-60],
		[x+60, y+60*2],
		[x-60, y+60*2],
		[x+60, y-60*2],
		[x-60, y-60*2],
		[x-60*2, y-60],
		[x-60*2, y+60]
	];
// закрашиваем их 
	
	for(var v=0;v<v1.length;v++){
		if(v1[v][0]>59 && v1[v][0]<481 && v1[v][1]>59 && v1[v][1]<481) 		{
			var f = new rect('#ffe800',v1[v][0],v1[v][1],60,60,0.4);
				f.draw();
		}
	}
//закрашиваем то, куда ходили
for (var i=0;i<arr.length;i++) {
		var f = new rect('#f00',arr[i][0],arr[i][1],60,60,1);
				f.draw();
}
	//рисуем коня
	imkago(x,y);
}
init();
function imkago(x,y) {
	var kon = new Image();
	kon.src = 'images/kon.png';
	kon.onload = function() {
		ctx.beginPath();
		ctx.globalAlpha = 1;
		ctx.drawImage(kon, x+3, y-45);	
	}
}

$('#chess').click(function(event){
 var x = event.pageX - this.offsetLeft-$('.chess').offset().left;
 var y = event.pageY - this.offsetTop;
	  	x = (Math.floor(x/60))*60;
		y = (Math.floor(y/60))*60;
//сравниваем, если нет совпадений. ничего не происходить, смотрим ошибки
		for (var j=0;j<arr.length;j++) {
			if (arr[j][0]==x && arr[j][1]==y){
				error++;
				$(".info").html("<p>Количество шагов: "+arr.length+"<p><p>Количество ошибок: "+error+"<p>");
				return false;
			}	
		}
	for(var v=0;v<v1.length;v++){	
			if(v1[v][0]==x && v1[v][1]==y) {
					init(x,y);
			}
	}
	$(".info").html("<p>Количество шагов: "+arr.length+"<p><p>Количество ошибок: "+error+"<p>");
})



В целом получилось не очень громоздко, но код далеко не идеален и не универсален. Больше подходить для понятия логики и основ программирование на javaScript. Надеюсь, статья будет кому-нибудь полезна, спасибо.
Tags:
Hubs:
-1
Comments7

Articles