БлогNot. Изучаем ходы шахматных фигур

Изучаем ходы шахматных фигур

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

Всё неплохо, но эпоха Visual Basic, Delphi, да и вообще stand-alone приложений давно прошла :)

Немного поработав вчера и сегодня, написал небольшой сервис для работы с фигурами на доске в режиме "перетащил и оставил".

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

Всё, что мне понадобилось - освежить в памяти примеры по chessboard.js и документацию по chess.js, эти замечательные библиотеки я уже использовал в "искусственном интеллекте" на Javascript.

Ниже показан сервис в работе, приведена содержательная часть кода и прикреплён архив с исходниками.

 Сервис Ходы шахматных фигур, открыть в новом окне (вкладке)

Если на Вашем экране недостаточно места по вертикали, в любом современном браузере можно перейти в полноэкранный режим отображения клавишей F11 или уменьшить масштаб страницы комбинацией клавиш Ctrl и "минус" (восстановить масштаб по умолчанию - Ctrl и "ноль")

Код главного файла index.html без стандартного обрамления на момент написания выглядит так:

<div class="info">
 <span id="instructionLink" style="cursor:pointer; text-decoration: underline;" 
  onclick="switchShow ();return false;">ИНСТРУКЦИЯ</span>
 <a href="javascript:window.location.reload(true);">ЗАНОВО</a>
</div>
<div class="info" id="instructionBox" style="display: none;">
 <p>Перетащите фигуры на доску, чтобы посмотреть, как они ходят.
  <br>Очередность хода переходит к фигуре, на которую вы навели мышку.
  <br> Чтобы сходить, перетащите мышкой фигуру на допустимое поле.
  <br> "Лишние" фигуры также можно убрать с доски мышкой.
 </p>
</div>
<div id="board" class="board"></div>
<div class="info">
 <p><b>Состояние</b>: <span id="status"></span></p>
 <p><b>Позиция</b>: <span id="fen"></span></p>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src='http://scripts.kislenko.net/aichess/js/chess.js'></script>
<script src='http://scripts.kislenko.net/aichess/js/chessboard.js'></script>
<script src='js/script.js'></script>
<noscript>
 <div align="center">
  Извините, для работы приложения нужен включённый Javascript в браузере
 </div>
</noscript>

Файл js/script.js, содержащий логику проекта, выглядит так:

var emptyPosition = '4k3/8/8/8/8/8/8/4K3 w - - 0 1'; 
 //Начальная позиция, рокировки не разрешены
var board,
  game = new Chess (emptyPosition),
  statusEl = $('#status'),
  fenEl = $('#fen');

var onDragStart = function(source, piece, position, orientation) { //Разрешаем перетаскивать всё
};

var onDrop = function (source, target, piece, newPos, oldPos) { //Роняем фигуру
 removeGreySquares();
 if (target === 'offboard') { //Вне доски - убрать фигуру из игры
  game.remove (source);
 }
 else if (source === 'spare') { //Притащили из коллекции - добавить фигуру в игру
  var color = piece.substring(0,1);
  game.put({type: piece.substring(1).toLowerCase(), color: color}, target);
 }
 else { //Это ход по доске
  var move = game.move({
    from: source,
    to: target,
    promotion: 'q' //Для простоты превращение всегда в ферзя
  });
  if (move === null) return 'snapback'; //Ход недопустим - отменить
 }
 updateStatus(); //Обновить статус
};

var onSnapEnd = function() { 
 //Обновить позицию после особых ходов (превращение, взятие на проходе, рокировка)
 board.position(game.fen());
 updateStatus();
};

var onMouseoutSquare = function(square, piece) { //Мышка уходит с клетки
 removeGreySquares();
};

var removeGreySquares = function() { //Убрать фон
 $('#board .square-55d63').css('background', '');
};

var onMouseoverSquare = function (square, piece) { //Мышка входит на поле
 if (piece) { //Если на поле есть фигура
  var color=piece.substring(0,1); //то её цвет определяет очередность хода
  var tokens = game.fen().split(' ');
  tokens[1] = color;
  game.load (tokens.join(' '));
  updateStatus ();
 }
 var moves = game.moves({ //Получить список ходов для поля
  square: square,
  verbose: true
 });
 if (piece) greySquare (square); //Подсветить текущее поле
 if (moves.length === 0) return; //Если у фигуры нет ходов - выйти
 for (var i = 0; i < moves.length; i++) { //Подсветить поля, куда можно ходить
  greySquare(moves[i].to);
 }
};

var greySquare = function(square) { //Непосредственно функция подсветки полей
 var squareEl = $('#board .square-' + square);
 var background = '#99ff99'; //Цвет подсветки белых полей
 if (squareEl.hasClass('black-3c85d') === true) {
  background = '#03c03c'; //Цвет подсветки чёрных полей
 }
 squareEl.css('background', background);
};

var updateStatus = function() { //Обновление статуса
 var status = '';
 var moveColor = 'белые';
 if (game.turn() === game.BLACK) {
  moveColor = 'чёрные';
 }
 if (game.in_checkmate() === true) { //Мат
  status = 'Вне игры, ' + moveColor + ' получили мат';
 }
 else if (game.in_draw() === true) { //Ничья
  status = 'Вне игры, ничья';
 }
 else {
  status = moveColor + ' могут ходить';
  if (game.in_check() === true) { //Шах
   status += ', ' + moveColor + ' под шахом';
  }
 }
 statusEl.html(status);
 fenEl.html(game.fen());
};

var cfg = { //Конфигурация доски
 draggable: true,
 dropOffBoard: 'trash',
 sparePieces: true,
 position: emptyPosition,
 onDragStart: onDragStart,
 onDrop: onDrop,
 onMouseoutSquare: onMouseoutSquare,
 onMouseoverSquare: onMouseoverSquare,
 onSnapEnd: onSnapEnd
};
board = ChessBoard('board', cfg);
updateStatus();

function switchShow (id) { //Переключалка видимости для вывода инструкции
 var div=document.getElementById ('instructionBox');
 div.style.display = div.style.display == "none" ? "block" : "none";
 document.getElementById ('instructionLink').innerHTML = 
  div.style.display == "block" ? "СКРЫТЬ ИНСТРУКЦИЮ" : "ИНСТРУКЦИЯ";
 return false;
}

 Скачать архив .zip с проектом Ходы фигур, развернуть без создания новой папки (32 Кб)

Исходники приведены на момент написания, в прикреплённом архиве они могут быть изменены или улучшены.

Технические замечания:

Скрипт не использует ходы-рокировки и взятия на проходе, для игры по всем правилам есть другой скрипт, а этот предназначен, в основном, для освоения простейших навыков и правил игры.

Пешка для простоты всегда превращается в ферзя, если нужен выбор превращения, подойдёт решение из этой статьи блога.

Чтобы разрешить взятие на проходе, закомментируйте в js/script.js строку с пометкой "Убрать метку проходного поля".

Рокировку можно разрешить, просто загружая соответствующие начальные позиции, то есть,

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

вместо

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 1

Скрипт не даёт поставить новые фигуры на доску "неправильно", то есть, пешки на первую или восьмую горизонталь, а также "лишних" королей или двух королей рядом. При этом, добавляемый на доску новый король может заменить другого короля на том же поле доски - это не баг, а фича :)

Известные баги:

При короле на поле a7 или a8 и отсутствии короля у противоположной стороны статус игры показывается неверно. Источник бага - ошибка в chess.js, правда, bug issue автор сразу же закрыл.

Скриншот приложения (фрагмент экрана, подсвечены доступные поля для ладьи)
Скриншот приложения (фрагмент экрана, подсвечены доступные поля для ладьи)

07.12.2017, 11:33 [3893 просмотра]


теги: программирование игра javascript шахматы сервис

К этой статье пока нет комментариев, Ваш будет первым