Как рассчитать расстояние между двумя квадратами на сетке, включая целевой квадрат - PullRequest
2 голосов
/ 02 февраля 2020

Я пробовал варианты для следующего кода ...

public int Distance2D(int x1, int y1, int x2, int y2)
{
    //     ______________________
    //d = √ (x2-x1)^2 + (y2-y1)^2
    //

    //Our end result
    int result = 0;
    //Take x2-x1, then square it
    double part1 = Math.Pow((x2 - x1), 2);
    //Take y2-y1, then sqaure it
    double part2 = Math.Pow((y2 - y1), 2);
    //Add both of the parts together
    double underRadical = part1 + part2;
    //Get the square root of the parts
    result = (int)Math.Sqrt(underRadical);
    //Return our result
    return result;
}

Приведенные ниже примеры оставлены для ясности, но были ошибочными из-за моей ошибки

Distance2D (1, 1, 1, 2) // возвращает 1 - правильно
Distance2D (1, 1, 2, 1) // возвращает 1 - правильно
Distance2D (1, 1, 2, 2) // возвращает 1 - правильно
Distance2D (1, 1, 5, 5) // возвращает 5 - правильно

Distance2D (0, 2, 5, 8) // возвращает 7 - неверно, должно быть 8
Distance2D (1, 1, 5, 3) // возвращает 4 - неверно, должно быть 5
Distance2D (10, 112, 15, 118) // возвращает 7 - неверно, должно быть 8

Есть ли лучшая формула для этого?

Обновление

У меня были некоторые из моих ожидаемых значений выше неправильных из-за того, что они ошибочно взяли начало 2-й координаты из местоположения 1-й. * Я пытаюсь получить количество ходов, которое потребуется сделать игровому элементу, чтобы проехать от одного к координировать с другим на квадратной сетке. Перемещаясь по одному квадрату за раз, диагонали также учитываются как 1 ход.

Таким образом ...

  • от 1,1 до 5,5 потребует 4 диагональных движения и одно горизонтальное / вертикальное движение в общей сложности 5 ходов. Возвращает правильно
  • от 1,1 до 5,3 потребует 3 диагонали и 1 горизонтальное / вертикальное движение в общей сложности 4 хода. Теперь это правильно возвращает
  • от 1,1 до любого из 1,2 / 2,1 / 2,2 - один ход. Каждый из них возвращает корректно
  • от 0,2 до 5,8 - это 5 диагональных ходов и одно вертикальное движение в общей сложности 6 ходов. Это возвращает 7 неправильно

Если я использую Math.Round() в результате, то я получаю следующие ошибки ...

  • с 0,2 до 5,8 возвращает 8 вместо 6
  • 1,1 до 5,5 возвращает 6 вместо 5

Если я использую Math.Ceiling(), я получаю следующие ошибки ...

  • от 0,2 до 5,8 возвращает 8 вместо 6
  • от 1,1 до 2,2 возвращает 2 вместо 1
  • 1,1 до 5,3 возвращает 4 вместо 5

1 Ответ

2 голосов
/ 02 февраля 2020

Проблема заключается в том, что выполнение приведения ((int)) эффективно выполняет "минимальную" операцию над вашим числом, обрезая все десятичные значения, даже если эти десятичные значения равны .99999. Похоже, вместо этого вы хотите округлить значение до ближайшего целого числа, что можно сделать с помощью функции Math.Round().

Попробуйте сделать следующее:

result = (int)Math.Round(Math.Sqrt(underRadical));

Обновить

Подход, основанный на теоремах Пифагора, который вы используете, не сработает для того, что вы пытаетесь вычислить. Это совершенно другой вариант использования. Хорошая новость в том, что ваш вариант использования намного проще. Просто определите расстояние, которое вам нужно пройти по каждой оси, затем вычтите все возможные комбинации, двигаясь по диагонали. Как-то так, я думаю:

var yDist = Math.Abs(y2 - y1);
var xDist = Math.Abs(x2 - x1);
var diagShortcut = Math.Min(yDist, xDist);
return yDist + xDist - diagShortcut;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...