2015-04-03 46 views
1

所以我得到了这样的问题:我想从一个黑点移动到另一个像这样:如何使某物在矩阵中以特定顺序移动?

enter image description here

,但每当我试图做到这一点,它的动作是这样的:

enter image description here

您只能在一个方向移动:北,南,东,西一次。 我试图做这样的事情:

 int distance = game.Distance(myPirate.Loc,loc); 
     List<Direction> allDirections = new List<Direction>() { Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.NOTHING }; 
     Location destination; 
     foreach (Direction dir in allDirections) 
     { 
      destination = game.Destination(myPirate, dir); 
      int distance2 = game.Distance(destination, loc); 
      if (distance2 < distance) return dir; 
     } 
     return Direction.NOTHING; 

但每当我试试这个代码,我得到这些结果:

enter image description here

谁能帮我弄清楚如何像第一画面移动和不喜欢第二个?你得到矩阵中2个黑方块的位置。 如果您还需要更多,请告诉我。

+1

像直线(欧几里德)距离作为启发式函数的A *搜索可能会应用? – 2015-04-03 22:58:31

+1

@ap或者如果您看另一种方式[DDA线条绘图](http://en.wikipedia.org/wiki/Digital_differential_analyzer_%28graphics_algorithm%29)或其他线条绘制算法。 – 2015-04-03 23:16:17

+0

我不明白如何使用它,线绘图算法怎么可以帮助我呢? :( – 2015-04-04 06:11:25

回答

0

尝试用随机的目录“(在allDirections方向Dir)”,以使它可以检查不同的方向顺序每一次,去的曲折方式..

因为它总是在同一方向顺序检查北>南>西>东>没有任何东西在直线上。

+0

我不能那样做,不能转换方向int – 2015-04-04 05:53:06

1

由于@ap和@AlexeiLevenkov在他们的评论中已经提到,您可以使用任何线条绘制算法来解决您的任务。

将您的矩阵看作像素字段(屏幕)。你想以最短的方式从起点移动到终点,这当然是一条直线(我确信你可以从几何学课程中记住这一点)。所以你必须在栅格像素字段上的两点之间“绘制”一条直线。这正是这些绘图算法的要点。

让我们使用简单的DDA。

首先,你要确定你的路径线斜率:

double slope = (endPoint.Y - startPoint.Y)/(double)(endPoint.X - startPoint.X); 

那么你应该看看斜率绝对值是否小于或大于1。这是根据算法。如果它小于或等于1,那么我们将在每个步骤的水平方向上移动(所以我们“采样”dX = 1)。在另一种情况下,我们将沿垂直方向移动(“采样”为dY = 1)。

我们必须准备我们的“行”:我们计算DXDY偏移根据坡度。对于案例dX == 1,我们将在每次移动中向左或向右移动,并且另外使用dY值计算下一个垂直“跳跃”。如果我们确定我们应该向上或向下移动,那么我们通常会另外做到这一点。但是由于每次迭代只允许一次移动,我们将需要跳过水平移动并改为垂直移动。

在下一个示例代码中,我将省略dY == 1的情况。你一定可以自己写。此外,这段代码并不是那么简洁,但为了简单起见,我就这样离开它。您可以优化并重构它。

private double dX, dY; 
private double currentX, currentY; 

void PrepareMoving(Point startPoint, Point endPoint) 
{ 
    double slope = (endPoint.Y - startPoint.Y)/(double)(endPoint.X - startPoint.X); 
    if (Math.Abs(slope) <= 1.0) 
    { 
     this.dX = Math.Sign(endPoint.X - startPoint.X); 
     this.dY = slope; 
    } 
    else 
    { 
     this.dY = Math.Sign(endPoint.Y - startPoint.Y); 
     this.dX = slope; 
    } 

    this.currentX = startPoint.X; 
    this.currentY = startPoint.Y; 
} 

Direction DoNextMove(Point target) 
{ 
    // If we already have reached the destination... 
    if (new Point((int)this.currentX, (int)this.currentY) == target) 
    { 
     return Direction.NOTHING; 
    } 

    // if the horizontal moving is "primary" 
    if (Math.Abs(this.dX) == 1.0) 
    {  
     double nextValue = this.currentY + this.dY; 
     try 
     { 
      // we have to move up or down if we've got a "jump" 
      if (Math.Round(nextValue) != Math.Round(this.currentY)) 
      { 
       return this.dY > 0 ? Direction.SOUTH : Direction.NORTH; 
      } 
      // otherwise, just perform the "normal" left or right move 
      else 
      { 
       this.currentX += this.dX; 
       return this.dX > 0 ? Direction.EAST : Direction.WEST; 
      } 
     } 
     finally 
     { 
      // ensure we set the current values for the next move 
      this.currentY = nextValue; 
     } 
    } 
    else 
    { 
     // You know what to do here: vertical moving is "primary" 
    }  
}