views:

275

answers:

3

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?

+1  A: 

[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.

Stefan Kendall
+1  A: 

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.

Argalatyr
...you're right, of course. I'm not sure what I was thinking when I wrote that. I've been having a lot of trouble representing grids lately, and sometimes they come out the one way and sometimes the other, and it's driving me up the wall.
Mason Wheeler
I updated it with a better example that does demonstrate the problems I've been having.
Mason Wheeler
+4  A: 

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.

Argalatyr