Как я могу представить координатную сетку в Delphi?

Я пытаюсь представить двумерную координатную сетку двумерным массивом. Проблема в том, что объявление массива переворачивает координаты X и Y из-за того, как Delphi выделяет массив. Это затрудняет чтение элементов массива. Например, следующая программа выдает ошибку проверки диапазона при попытке печати:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

{$R+}
procedure play;
var
   grid: array of array of boolean;
   x, y: integer;
begin
  try
   setLength(grid, 3, 8);
   grid[1, 5] := true;
   for y := low(grid) to high(grid) do
   begin
      for x := low(grid[y]) to high(grid[y]) do
      begin
         if grid[x, y] then
            write('X')
         else write('.');
      end;
      writeln;
   end;
   readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end;

begin
   play;
end.

Я должен написать индекс задом наперед (если сетка [y, x], то), чтобы этого не произошло, но тогда сетка выводится боком, а X отображается в (5, 1) вместо (1, 5). Если я попытаюсь изменить форму сетки, сказав setLength(grid, 3, 8); то присваивание в следующей строке дает ошибку проверки диапазона. В итоге мне приходится записывать все мои координаты в обратном порядке, и каждый раз, когда я забываю, что они в обратном порядке, в программе начинают происходить плохие вещи.

Кто-нибудь знает какие-нибудь хитрости, чтобы порядок координат работал интуитивно?


person Mason Wheeler    schedule 03.07.2009    source источник


Ответы (3)


Вам просто нужно указать правильные границы в операторах for. Важно соблюдать осторожность при применении функций low и high к многомерным массивам. Для текущего примера (двумерный массив) low(grid) и high(grid) вернут ограничения для первого измерения (строки), тогда как low(grid[0]) и high(grid[0]) вернут вернуть ограничения для первого столбца (при условии, что он существует). Обратите внимание на измененные ограничения for ниже:

program Play_console;

{$APPTYPE CONSOLE}

uses
  SysUtils;

{$R+}
procedure play;
var
   grid: array of array of boolean;
   x, y: integer;
begin
  try
   setLength(grid, 3, 8);
   grid[1, 5] := true;
   for y := low(grid[0]) to high(grid[0]) do
   begin
      for x := low(grid) to high(grid) do
      begin
         if grid[x, y] then
            write('X')
         else write('.');
      end;
      writeln;
   end;

   readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end;

begin
   play;
end.

Я проверил это, и, похоже, он делает именно то, что вы хотите.

person Argalatyr    schedule 04.07.2009

[y, x] является общим и стандартным доступом к массиву в большинстве (всех?) языков программирования. Любой, кто посмотрит на ваш код, будет сбит с толку, если вы сделаете это иначе.

person Stefan Kendall    schedule 03.07.2009

Я бы сказал, что стандартное представление не только соответствует общепринятым правилам программирования, но и оно согласуется с построением графиков в целом. Постройте [1,4] на миллиметровой бумаге, и вы получите то же самое, что и во втором (фактическом результате) примере, за исключением того, что ось y перевернута в экранных координатах, но вы не жалуетесь на это.

Точнее, ось x постоянно горизонтальна, а ось y постоянно вертикальна. Это то, что показывает ваш пример. Это не наоборот.

Я бы сказал, просто привыкните.

person Argalatyr    schedule 04.07.2009
comment
... ты прав, конечно. Не знаю, о чем я думал, когда писал это. В последнее время у меня было много проблем с представлением сеток, и иногда они получались в одну сторону, а иногда в другую, и это сводило меня с ума. - person Mason Wheeler; 04.07.2009
comment
Я обновил его лучшим примером, который демонстрирует проблемы, с которыми я столкнулся. - person Mason Wheeler; 04.07.2009