I have a game consisting of ships that fly around on a 2d grid. I am writing a function that takes a location, and figures out if the (predefined) target can be hit from there. This simply requires checking all the grid square's in the potential aggressor's line of fire.
In most cases, this is a cross, formed like so:
(currX +/- SHOT_RANGE, currY) and (currX, currY +/- SHOT_RANGE)
Where SHOT_RANGE
is the maximum distance a shot can travel, and the firing ship is currently located at (currX, currY)
.
The code to check these two lines is fairly straightforward:
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;
}
}
However, on certain "power tiles" the ship can also fire diagonally. All these squares must be checked, too. This is where the repetition comes in. Can you see a way to do this with less code?
/// <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;
}
UPDATED to use Carra's suggestion, and I realized I could eliminate two of the loops checking diagonals by increasing the upper bounds.