Question

I'm trying to represent a two-dimensional coordinate grid with a two-dimensional array. Problem is, declaring the array flips the X and Y coordinates because of the way Delphi allocates the array. This makes it difficult to read elements of the array. For example, the following program gives a range check error while trying to print:

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.

I have to write the index backwards (if grid[y, x] then) to keep that from happening, but then the grid prints out sideways, with the X shown at (5, 1) instead of at (1, 5). If I try to change the shape of the grid by saying setLength(grid, 3, 8); then the assignment on the next line gives a range check error. I end up having to write all of my coordinates backwards, and any time I forget they're backwards, bad things end up happening in the program.

Does anyone know any tricks to make the coordinate order work intuitively?

Was it helpful?

Solution

You just need to give the proper bounds in the for statements. It's important to pay careful attention when applying the low and high functions to multi-dimensional arrays. For the current example (a 2-dimensional array), low(grid) and high(grid) will return the limits on the first dimension (row), whereas low(grid[0]) and high(grid[0]) will return the limits on the first column (assuming it exists). Note the changed for limits below:

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.

I tested this and it seems to do exactly what you want.

OTHER TIPS

[y, x] is common and standard array access across most (all?) programming languages. It will be confusing for anyone looking at your code if you do it otherwise.

I'd say that the standard representation isn't only consistent with general programming convention, it's consistent with graphing in general. Plot [1,4] on graph paper and you'll get the same thing as in your second (actual result) example, with the exception that the y axis is flipped in screen coordinates, but you're not complaining about that.

More specifically, the x axis is consistently horizontal, and the y axis is consistently vertical. That's what your example shows. It's not reversed.

I'd say just get used to it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top