Как определить, свободна ли дорожка от препятствий в шахматах? - PullRequest
2 голосов
/ 29 ноября 2010

У меня есть 2D-массив, содержащий все объекты Piece, каждый экземпляр Rook, Bishop, King и т. Д. ...

Как узнать, является ли путь от srcX, srcY до dstX, dstYпрепятствует другой части?

Единственное, что я могу придумать, будет включать в себя огромное количество утомительного кода = /

Ответы [ 10 ]

7 голосов
/ 29 ноября 2010

Ваш комментарий о "огромном количестве утомительного кода" - огромное преувеличение.Ни один путь на шахматной доске не превышает восьми квадратов, и все они могут следовать простому алгоритму - увеличивать или уменьшать счетчик строк и / или столбцов.(За исключением рыцаря, который может двигаться только на восемь квадратов и не может быть заблокирован.) Я сомневаюсь, что код для любой фигуры занимает более двадцати строк.

Например, вот код для слона:

// check move legality not taking into account blocking
  boolean canMoveBishopTo(int srcx,int srcY,int destX,int destY) {
      if (srcX<0 || srcX>7 ||srcY<0 || srcY>7 || destX<0 || destX>7 ||destY<0 || destY>7) {
        throw new IllegalArgumentException();
      }
      if ((srcX==destX || srcY==destY) {
        return false;
      }

      if (Math.abs(destX-srcX) == Math.abs(srcY-destY) {
        return true;
      }
      return false;
    }

boolean isBishopMoveBlocked(int srcx,int srcY,int destX,int destY) {
  // assume we have already done the tests above
  int dirX = destX>srcX ? 1 : -1;
  int dirY = destY>srcY ? 1 : -1;
  for (int i=1;i<Math.abs(destX-srcX)-1;++i) {
    if (pieceOnSquare(srcX+i*dirX,srcY+i*dirY) {
      return false;
    }
  }
  return true;
}
4 голосов
/ 29 ноября 2010

У нас есть начальная и конечная точки, и мы знаем, что нам нужно смотреть только на горизонтальные, вертикальные или диагональные линии.

Сначала вычислите вектор направления . Это 2D точка со значениями вроде

Point north = new Point(0,1);
Point northEast = new Point(1,1);
Point east = new Point(1,1);
// ...
Point northWest = new Point(-1,1);

Это довольно просто:

Point start = getStart();
Point dest = getDest();
Point direction = new Point(Math.signum(dest.x-start.x), 
                            Math.signum(dest.y-start.y));

(Пример: начало = (2,2), пункт назначения = (7,7) -> (знак (7-2), знак (7-2)) = (1,1))

Теперь просто увеличивайте положения доски на точку направления, пока не достигнете места назначения, и проверьте для каждой 2D-точки, содержит ли место часть.

Вот быстрый черновик (примите его как псевдокод, если он не компилируется;))

Point start = getStart();
Point dest = getDest();
if (start.equals(dest)) return false; // nothing in between by definition

Point direction = new Point(Math.signum(dest.x-start.x), 
                            Math.signum(dest.y-start.y));
Point current = new Point(start.x+direction.x, start.y+direction.y);
while(!current.equals(dest)) {
  if (isOccupied(board[current.x][current.y])) // test to be implemented
     return true; // something in between
  current.x = current.x + direction.x;
  current.y = current.y + direction.y;      
}
return false; // nothing in between
1 голос
/ 29 ноября 2010

Необходимо выполнить два условия:

  1. dst не могут быть заняты тем же самым цветом
  2. Все другие (не рыцарь) ходы либо диагонали,горизонтальный или вертикальный.Так что просто проверьте, что в соседних строках, столбцах или диагональных элементах вашего массива нет существующих частей между src и dst
0 голосов
/ 29 ноября 2010

Эта проблема хорошо подходит для решения с массивом (возможно, поэтому оно было назначено в качестве упражнения с массивом).Кажется, что вам не хватает того, что каждое из нескольких направлений может быть выполнено с использованием знака шага, поэтому в коде вам не нужно явно обрабатывать каждое направление.В псевдокоде:

steps_bishop = [[1,1], [1,-1], [-1, 1], [-1,-1]] # an array of each possible step direction (which are also arrays)
steps_rook = [[1,0], [-1,0], [0, 1], [0,-1]]

# everything else is agnostic to step direction:
current_position = get_current_position()
steps = steps_bishop  # step like a bishop, for example

for step_direction in steps:
    while still_on_board(current_position) and no_collision(current_position):
        current_position += step_direction
0 голосов
/ 29 ноября 2010

Пусть двумерный массив представляет собой доску, пустые места, фигуры и все.

Есть 8 направлений, которые необходимо проверить.

  1. Вверх и вправо.
  2. Вверх.
  3. Вверх и влево.
  4. Влево.
  5. Вниз и влево.
  6. Вниз.
  7. Вниз и вправо.
  8. Справа.

Теперь вам просто нужно знать, как увеличивать / уменьшать ваши индексы и проверять позиции на пустоту.

Надеюсь, я не отдал слишком много.

0 голосов
/ 29 ноября 2010

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

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

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

Основная функция просто получит использованное направление (через dst-src, интерпретируемое как вещь, подобная коэффициенту, и сокращенное допростейшие термины) и проверяйте, не мешает ли фигура.

0 голосов
/ 29 ноября 2010

Все зависит от того, какой тип доски вы выберете. Тот, который вы выбираете, прост для начала, но вы очень быстро сталкиваетесь с проблемами производительности. Так что да, вам нужно будет написать несколько утомительных объемов кода. Это может помочь вам сгенерировать этот код вместо того, чтобы писать его вручную. С другой стороны, вас могут заинтересовать другие представления. Например, битборды представляют собой современное состояние и будут (правильно реализованы) давать огромные ускорения. Обратите внимание, что объем кода все еще может быть огромным и, конечно, гораздо более сложным. Вот введение Роберта Хаятта (автора Crafty), которое может вас заинтересовать: boardrep .

Удачи!

0 голосов
/ 29 ноября 2010

Я бы взглянул на A *, это один из самых популярных алгоритмов маршрутизации: http://en.wikipedia.org/wiki/A*_search_algorithm

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

0 голосов
/ 29 ноября 2010

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

0 голосов
/ 29 ноября 2010

Рассматривали ли вы представить свою шахматную доску в виде графика ?Затем вы можете просто пересечь график из точки A в точку B и посмотреть, есть ли на вашем пути какие-либо «узлы».

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