Как красиво записать в массив координаты 8 соседних клеток?

У меня есть код:

  void UpdateNeighborCells() {
        NeighborCells [0] = {position.x--, position.y};
        NeighborCells [1] = {position.x--, position.y--};
        NeighborCells [2] = {position.x++ , position.y--};
        NeighborCells [3] = {position.x-- , position.y++};
        NeighborCells [4] = {position.x++ , position.y++};
        NeighborCells [5] = {position.x, position.y--};
        NeighborCells [6] = {position.x , position.y++};
        NeighborCells [7] = {position.x++ , position.y};
  }

У каждого человечка в моей игре есть позиция, и мне надо знать его соседние клетки и обновлять их каждый раз, когда он ходит; этот метод как раз это и делает. Выглядит не очень красиво, есть ли идеи, как можно сократить количество строк и сделать более "красивым"?


Ответы (2 шт):

Автор решения: Kromster

Первое и важное, как подсказывает @StanislavVolodarskiy, вы перезаписываете значения переменных используя ++ и --. Врядли это то что вы хотите на самом деле сделать.

Самое простое для приближения к красоте и удобочитаемости это переменные покороче и выравнивание поровнее. Так вы хотя бы визуально будете видеть что всё в порядке (три раза +1, три раза -1 с каждой стороны и два раза просто):

  void UpdateNeighborCells() {
        p = position;

        NeighborCells [0] = {p.x-1, p.y  };
        NeighborCells [1] = {p.x-1, p.y-1};
        NeighborCells [2] = {p.x+1, p.y-1};
        NeighborCells [3] = {p.x-1, p.y+1};
        NeighborCells [4] = {p.x+1, p.y+1};
        NeighborCells [5] = {p.x  , p.y-1};
        NeighborCells [6] = {p.x  , p.y+1};
        NeighborCells [7] = {p.x+1, p.y  };
  }

Также не повредит комментарий с уточнением порядка обхода, для наглядности:

  // 152
  // 0x7
  // 364

Это кстати достаточно странный порядок, если алгоритм позволяет, то лучше поменять на что-то более очевидное, типа:

  // 012
  // 3x4
  // 567
→ Ссылка
Автор решения: Stanislav Volodarskiy

Я запустил ваш код и затем распечатал результат для исходной позиции (0, 0):

UpdateNeighborCells();
for (int i = 0; i < 8; ++i) {
    std::cout << i << ": (" << NeighborCells[i].x << ", " <<
        NeighborCells[i].y << ")\n";
}

Печать:

0: (0, 0)
1: (-1, 0)
2: (-2, -1)
3: (-1, -2)
4: (-2, -1)
5: (-1, 0)
6: (-1, -1)
7: (-1, 0)

Для наглядности я поместил индексы ячеек в таблицу, чтобы было видно каких соседей мы перебираем. Четыре ячейки пустые, в одной ячейке два индекса, в одной – три, диапазоны x и y смещены (должны быть [-1, 0, 1]):

x = -2 x = -1 x = 0
y = -2 3
y = -1 2, 4 6
y = 0 1, 5, 7 0

Я хочу сказать что это не работает. Речь не о красоте, а о правильности.

Заменим инкременты на обычные выражения без побочных эффектов:

void UpdateNeighborCells() {
    NeighborCells[0] = {position.x - 1, position.y    };
    NeighborCells[1] = {position.x - 1, position.y - 1};
    NeighborCells[2] = {position.x + 1, position.y - 1};
    NeighborCells[3] = {position.x - 1, position.y + 1};
    NeighborCells[4] = {position.x + 1, position.y + 1};
    NeighborCells[5] = {position.x    , position.y - 1};
    NeighborCells[6] = {position.x    , position.y + 1};
    NeighborCells[7] = {position.x + 1, position.y    };
}

Печать:

0: (-1, 0)
1: (-1, -1)
2: (1, -1)
3: (-1, 1)
4: (1, 1)
5: (0, -1)
6: (0, 1)
7: (1, 0)

Размещение изменилось, даже диапазон. И теперь все восемь соседей упомянуты в списке:

x = -1 x = 0 x = 1
y = -1 1 5 2
y = 0 0 7
y = 1 3 6 4

Уменьшить количество кода можно так:

void UpdateNeighborCells() {
    const int x = position.x;
    const int y = position.y;
    NeighborCells[0] = {x - 1, y    };
    NeighborCells[1] = {x - 1, y - 1};
    NeighborCells[2] = {x + 1, y - 1};
    NeighborCells[3] = {x - 1, y + 1};
    NeighborCells[4] = {x + 1, y + 1};
    NeighborCells[5] = {x    , y - 1};
    NeighborCells[6] = {x    , y + 1};
    NeighborCells[7] = {x + 1, y    };
}

Если хочется решение с инкрементами, то вот оно. Порядок обхода – слева по часовой стрелке:

void UpdateNeighborCells() {
    int x = position.x;
    int y = position.y;
    NeighborCells[0] = {--x,   y};  // шаг из центра налево
    NeighborCells[1] = {  x, --y};  // шаг вверх
    NeighborCells[2] = {++x,   y};  // два шага вправо
    NeighborCells[3] = {++x,   y};
    NeighborCells[4] = {  x, ++y};  // два шага вниз
    NeighborCells[5] = {  x, ++y};
    NeighborCells[6] = {--x,   y};  // два шага налево
    NeighborCells[7] = {--x,   y};
}
→ Ссылка