Программирование движения шахматной ладьи

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

Моя доска представляет собой простой двумерный целочисленный массив, значения которого равны 0,1,2, в зависимости от того, пусто ли место, имеет красный или черный фрагмент.

Мой код для движения пока показан ниже, он создает истинное или ложное значение, если движение разрешено или нет:

int[][] board;

public boolean validMove(int fromRow, int fromCol, int toRow, int toCol) {
    if(pieceAt(toRow, toCol) != EMPTY) {
        return false;
    }
    else if(fromRow - toRow == 0 && fromCol - toCol != 0) {
        return true;
    }
    else if(fromCol - toCol == 0 && fromRow - toRow != 0) {
        for(int i = fromRow; i < toRow; i++) { // Trying to add piece collision code
            if(pieceAt(toCol, i) != EMPTY) return false; // Trying to add piece collision code
        }
        return true;
    }
    else return false;
}

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

3 ответа

Решение

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

bool validMove(int fromRow, int fromCol, int toRow, int toCol)
{
    int i;

    // Attempt to move to the same cell
    if (fromRow == toRow && fromCol == toCol)
        return false;

    // Collision detection
    if (fromRow == toRow) {
        // Horizontal move
        if (fromCol < toCol) {
            // Move right
            for (i = fromCol + 1; i <= toCol; ++i)
                if (pieceAt(fromRow, i) != EMPTY)
                    return false;
        } else {
            // Move left
            for (i = fromCol - 1; i >= toCol; --i)
                if (pieceAt(fromRow, i) != EMPTY)
                    return false;
        }
    } else if (fromCol == toCol) {
        // Vertical move
        if (fromRow < toRow) {
            // Move down
            for (i = fromRow + 1; i <= toRow; ++i)
                if (pieceAt(i, fromCol) != EMPTY)
                    return false;
        } else {
            // Move up
            for (i = fromRow - 1; i >= toRow; --i)
                if (pieceAt(i, fromCol) != EMPTY)
                    return false;
        }
    } else {
        // Not a valid rook move (neither horizontal nor vertical)
        return false;
    }

    return true;
}

РЕДАКТИРОВАТЬ

Вы также можете оптимизировать свой код, уменьшив количество условных операторов, используя метод, предложенный Toon Krijthe. Основная идея состоит в том, чтобы использовать "дельта" значения (dx/dy) для увеличения или уменьшения индексов ячеек. В этом случае ячейка назначения должна быть проверена явно.

Код:

bool validMove(int fromRow, int fromCol, int toRow, int toCol)
{
    int i;

    // Attempt to move to the same cell
    if (fromRow == toRow && fromCol == toCol)
        return false;

    // Check if destination cell is free
    if (pieceAt(toRow, toCell) != EMPTY)
        return false;

    // Collision detection
    if (fromRow == toRow) { // Horizontal move
        int dx = (fromCol < toCol) ? 1 : -1;

        for (i = fromCol + dx; i != toCol; i += dx)
            if (pieceAt(fromRow, i) != EMPTY)
                return false;

    } else if (fromCol == toCol) { // Vertical move
        int dy = (fromRow < toRow) ? 1 : -1;

        for (i = fromRow + dy; i != toRow; i += dy)
            if (pieceAt(i, fromCol) != EMPTY)
                return false;
    } else { // Not a valid rook move
        return false;
    }

    return true;
}

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

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

Вы можете просто "пройтись" по каждому полю, чтобы проверить, не заполнено ли оно. Например:

int[][] board;

public boolean validMove(int fromRow, int fromCol, int toRow, int toCol) 
{
  if (pieceAt(toRow, toCol) != EMPTY) return false;
  else if (fromRow == toRow) 
  {
    // horizontal move
    if (fromCol == toCol) return false; // same position
    int dx, x;
    if (fromCol < toCol) 
      dx = 1;
    else 
      dx = -1; 

    for (x = fromCol + dx; x != toCol; x += dx) 
    {
      if (pieceAt(toRow, x) != EMPTY) return false; // occupied
    }
  }
  else if (fromCol == toCol) 
  {
    // vertical move
    int dy, y;
    if (fromRow < toRow) 
      dy = 1;
    else 
      dy = -1; 

    for (y = fromRow + dy; y != toRow; y += dy) 
    {
      if (pieceAt(y, toCol) != EMPTY) return false; // occupied

      return true; // free path
    }
  }
  else return false; // no horizontal or vertical move

}

Другие вопросы по тегам