2010-02-10 4 views
1

У меня есть игра, состоящая из кораблей, которые летают по 2-й сетке. Я пишу функцию, которая занимает место, и выясняет, может ли быть удалена (предопределенная) цель. Это просто требует проверки всех квадратов сетки в линии огня потенциального агрессора.C# XNA: Как удалить повторение с этой простой функции?

В большинстве случаев, это крест, образованный таким образом:

(currX +/- SHOT_RANGE, currY) and (currX, currY +/- SHOT_RANGE) 

Где SHOT_RANGE максимальное расстояние выстрела может путешествовать, и обжиг судно в настоящее время находится на (currX, currY).

код, чтобы проверить эти две линии довольно проста:

 for (int i = x - SHOT_RANGE; i < x + SHOT_RANGE; i++) { 
      if (target.TileX == i && target.TileY == y) { 
       return true; 
      } 
     } 

     for (int j = y - SHOT_RANGE; j < y + SHOT_RANGE; j++) { 
      if (target.TileX == x && target.TileY == j) { 
       return true; 
      } 
     } 

Однако, на некоторых «силовых плитки» судно может также стрелять по диагонали. Все эти квадраты также должны быть проверены. Здесь происходит повторение. Можете ли вы увидеть способ сделать это с меньшим количеством кода?

/// <param name="x">Current x-coord of the potential ship</param> 
    /// <param name="y">Current y-coord of the potential ship</param> 
      private bool CanShootTargetFrom(int x, int y) { 

     if ((target.TileX == x && Math.Abs(target.TileY - y) <= SHOT_RANGE) || (target.TileY == y && Math.Abs(target.TileX - x) <= SHOT_RANGE)) { 
      return true; 
     } 

     if (board.IsPowerTileAt(x, y)) { 
      int i = x - SHOT_RANGE; 
      int j = y - SHOT_RANGE; 
      while (i != x + SHOT_RANGE && j != y + SHOT_RANGE) { 
       if (target.TileX == i && target.TileY == j) { 
        return true; 
       } 
       i++; 
       j++; 
      } 
      i = x - SHOT_RANGE; 
      j = y + SHOT_RANGE; 
      while (i != x + SHOT_RANGE && j != y - SHOT_RANGE) { 
       if (target.TileX == i && target.TileY == j) { 
        return true; 
       } 
       i++; 
       j--; 
      } 
     } 

     return false; 
    } 

ОБНОВЛЕНО использовать предложение Карра, и я понял, что я мог бы устранить два петель проверки диагоналей путем увеличения верхних границ.

ответ

1

Я думаю, это может быть сделано проще без цикла, по крайней мере, для горизонтального и вертикального сканирования:

class Ship{int x;int y} 

Ship s;//your ship 
Ship t;//target 

if(
    (s.y == t.y && abs(s.x-t.x) <= SHOT_RANGE) 
    || 
    (s.x == t.x && abs(s.y-t.y) <= SHOT_RANGE) 
) 
    return true; 

Что касается диагоналей, они треугольник с углом 90 градусов: (a² + b² < c²)

int a = abs(s.x - t.x) 
int b = abs(s.y - t.y) 
if(a == b && a * a + b * b <= shot_range * shot_range) 
    return true; 

Я надеюсь, что это что-то подобное, что вы ищете?

+0

но для диагоналей это не будет возвращено true, если стрелка находится в '(3, 3)', а цель находится в '(1, 2)'? Это было бы неправильно; корабль стреляет по диагонали. (Итак, из '(3, 3)', корабль мог ударить '(2, 2)', '(1, 1)' и т. Д.) –

+0

Хорошая точка. Но это угол 90 градусов, так что == b. – Carra

0

Я думаю, что лучший дизайн будет изменить функцию, чтобы иметь подпись, аналогичную:
public bool CanShoot(IShootable potentialTarget)

Этот метод может быть членом класса кораблей. Каждый объект корабля будет знать свои собственные возможности стрельбы. Все, что вы хотели, чтобы иметь возможность быть застреленным, может реализовать IShootable.

Что касается вашего вопроса, кажется, это намного проще. Подобно тому, что сказал Карра, вы можете просто проверить, меньше ли абсолютная величина разницы в каждой координате, чем ваш диапазон стрельбы. Если нет, верните false. В противном случае, если они находятся на плитке власти, верните true. Если они не находятся на панели питания, убедитесь, что либо координата x, либо координата y совпадают, если не возвращать false, в противном случае верните true.

Это допущение, что судно с дальностью стрельбы 2 в точке (0,0) может стрелять на корабле в точке (2,2). Я предполагаю это, потому что указанный вами код позволит это.