Альтернативой стандартной плате 8x8 является почтовый ящик 10x12 (так называемый, потому что, я думаю, он выглядит как почтовый ящик). Это одномерный массив, который включает часовых вокруг своих «границ», чтобы помочь с генерацией хода. Это выглядит так:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", -1,
-1, "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", -1,
-1, "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", -1,
-1, "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", -1,
-1, "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", -1,
-1, "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", -1,
-1, "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", -1,
-1, "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1
Вы можете создать этот массив следующим образом (в JavaScript):
function generateEmptyBoard() {
var row = [];
for(var i = 0; i < 120; i++) {
row.push((i < 20 || i > 100 || !(i % 10) || i % 10 == 9)
? -1
: i2an(i));
}
return row;
}
// converts an index in the mailbox into its corresponding value in algebraic notation
function i2an(i) {
return "abcdefgh"[(i % 10) - 1] + (10 - Math.floor(i / 10));
}
Конечно, в реальной реализации вы бы поместили реальные кусочные объекты там, где находятся метки доски. Но вы бы оставили отрицательные (или что-то эквивалентное). Эти местоположения делают генерацию ходов намного менее болезненной, потому что вы можете легко определить, когда сбежали с доски, проверив это специальное значение.
Давайте сначала посмотрим на создание законных ходов для коня (нескользящая фигура):
function knightMoves(square, board) {
var i = an2i(square);
var moves = [];
[8, 12, 19, 21].forEach(function(offset) {
[i + offset, i - offset].forEach(function(pos) {
// make sure we're on the board
if (board[pos] != -1) {
// in a real implementation you'd also check whether
// the squares you encounter are occupied
moves.push(board[pos]);
}
});
});
return moves;
}
// converts a position in algebraic notation into its location in the mailbox
function an2i(square) {
return "abcdefgh".indexOf(square[0]) + 1 + (10 - square[1]) * 10;
}
Мы знаем, что действительные ходы Рыцаря находятся на фиксированном расстоянии от начальной точки фигуры, поэтому нам нужно было только проверить, что эти локации действительны (т. Е. Не часовые квадраты).
Скользящие части не намного сложнее. Давайте посмотрим на епископа:
function bishopMoves(square, board) {
var oSlide = function(direction) {
return slide(square, direction, board);
}
return [].concat(oSlide(11), oSlide(-11), oSlide(9), oSlide(-9));
}
function slide(square, direction, board) {
var moves = [];
for(var pos = direction + an2i(square); board[pos] != -1; pos += direction) {
// in a real implementation you'd also check whether
// the squares you encounter are occupied
moves.push(board[pos]);
}
return moves;
}
Вот несколько примеров:
knightMoves("h1", generateEmptyBoard()) => ["f2", "g3"]
bishopMoves("a4", generateEmptyBoard()) => ["b3", "c2", "d1", "b5", "c6", "d7", "e8"]
Обратите внимание, что функция slide
является общей реализацией. Вы должны быть в состоянии довольно легко смоделировать законные ходы других скользящих частей.