如何确定国际象棋中的路径是否没有障碍?

时间:2010-11-29 15:32:55

标签: java arrays algorithm

我有一个包含所有Piece对象的2D数组,每个对象都是Rook,Bishop,King等实例......

如何判断srcX,srcY到dstX,dstY的路径是否被其他路径阻挡?

我唯一能想到的就是涉及大量繁琐的代码= /

10 个答案:

答案 0 :(得分:7)

你对“大量繁琐的代码”的评论是一种夸张的夸张。棋盘上的路径不超过八个方格,并且所有这些路径都可以跟随一个简单的算法 - 递增或递减行和/或列计数器。 (除了骑士,它只能移动到八个方格并且不能被阻挡。)我怀疑任何一块的代码需要超过二十行。

例如,这里是主教的代码:

// 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;
}

答案 1 :(得分:4)

我们有一个起点和目的地点,并知道我们只需要看水平,垂直或对角线。

首先,计算方向向量。这是一个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));

(例如:start =(2,2),destination =(7,7) - &gt;(signum(7-2),signum(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

答案 2 :(得分:1)

需要满足两个条件:

  1. dst不能被a占用 一块相同的颜色
  2. 所有其他(非骑士)动作都是 对角线,水平或 垂直。所以只检查相邻的行, 您的列或对角条目 数组在srcdst
  3. 之间没有现有作品

答案 3 :(得分:0)

不是每次想要知道它而是计算它,可能更容易跟踪每件作品的所有可能性。

答案 4 :(得分:0)

我看看A *,它是最受欢迎的路径算法之一: http://en.wikipedia.org/wiki/A*_search_algorithm

它可能比您想要输入的代码更多,但它可能在其他地方使用的知识非常有用

答案 5 :(得分:0)

这完全取决于您选择的董事会代表。你选择的那个很容易开始,但你会很快遇到性能问题。所以是的,你需要编写一些繁琐的代码。它可以帮助您生成此代码,而不是手动编写。另一方面,您可能对其他表示感兴趣。例如,位板是最先进的,并且(正确实施)将提供巨大的加速。请注意,代码量可能仍然很大,当然要复杂得多。以下是Robert Hyatt(Crafty的作者)的介绍,您可能会感兴趣:boardrep

祝你好运!

答案 6 :(得分:0)

由于棋子都是直线移动而没有跳跃(除了骑士),所以编写一个函数来检查从src到dst的(直线)是否通过一个片段就足够了,并且每次都使用它除了骑士之外的部分(总是能够到达目的地)。

当然,对于所有作品,目的地广场应为空。

到达目的地实际上应该是一个合法的举动 - 如果有必要,也不应该太难检查。

主要功能只是获取使用的方向(通过dst-src解释为类似比例的东西并简化为最简单的术语)并循环检查一块是否挡路。

答案 7 :(得分:0)

让2D数组代表棋盘,空格,棋子等等。

您需要检查8个方向。

  1. 向上和向右。
  2. 向上。
  3. 向上和向左。
  4. 向下和向左。
  5. 向下。
  6. 向下和向右。
  7. 右键。
  8. 现在你只需要知道如何增加/减少指数并测试空位的位置。

    希望我没有放弃太多。

答案 8 :(得分:0)

这个问题很好地解决了数组解决方案(这可能是它被分配为数组练习的原因)。您似乎缺少的是,使用步骤的符号可以完成多个方向中的每个方向,因此在代码中您不需要明确地处理每个方向。在伪代码中:

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

答案 9 :(得分:-1)

您是否考虑将您的国际象棋棋盘表示为graph?然后,您可以简单地从A点到B点遍历图形,看看是否有任何“节点”。