Recent

Author Topic: Checking Adjacent Elements In 2D Array  (Read 2563 times)

WhatIsArrayPls

  • Newbie
  • Posts: 2
Checking Adjacent Elements In 2D Array
« on: November 21, 2018, 12:21:07 am »
Hey guys, I made a function that checks whether there are any elements in the adjacents cells (right, left, up and down). I tried this :

Code: Pascal  [Select][+][-]
  1. Function NoAdjacentElements(Board:TwoDArray;pY,pX,Length:Integer;Horizontal:boolean):boolean;
  2.  
  3. var PosX,PosY:integer;
  4.  
  5. Begin
  6.     PosX := pX;
  7.     PosY := pY;
  8.  
  9.     If (Horizontal = True) and ((PosX+Length)<20) then
  10.         While (pX<=PosX+Length) do begin
  11.             If (pY<20) and (Board[pY+1,pX]<>'*') then
  12.                 NoAdjacentElements := False;
  13.             If (pY>1) and (Board[pY-1,pX]<>'*') then
  14.                 NoAdjacentElements := False;
  15.             If (pX<20) and (Board[pY,pX+1]<>'*')  then
  16.                 NoAdjacentElements := False;
  17.             If (pX>1) and (Board[pY,pX-1]<>'*') then
  18.                 NoAdjacentElements := False;
  19.                 pX := pX + 1;
  20.             If pX = PosX+Length then
  21.                 NoAdjacentElements := True;
  22.         end;
  23.     If (Horizontal = False) and ((PosY+Length)<20) then
  24.         While (py<=PosY+Length) do begin
  25.             If (pY<20) and (Board[pY+1,pX]<>'*') then
  26.                 NoAdjacentElements := False;
  27.             If (pY>1) and (Board[pY-1,pX]<>'*') then
  28.                 NoAdjacentElements := False;
  29.             If (pX<20) and (Board[pY,pX+1]<>'*')  then
  30.                 NoAdjacentElements := False;
  31.             If (pX>1) and (Board[pY,pX-1]<>'*') then
  32.                 NoAdjacentElements := False;
  33.                 pY := pY + 1;
  34.             If (pY = PosY+Length) then
  35.                 NoAdjacentElements := True;
  36.         end;
  37. end;

Board is a two dimentional array, 20x20 made of chars.
pY and pX are generated randomly, they always have values between 1 and 20.

However, once I run the whole thing, I end up with adjacents characters anyway. If possible, I would like for you guys to point if there's any kind of mistake with this function, or maybe I'm just using this function the wrong way.


lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Checking Adjacent Elements In 2D Array
« Reply #1 on: November 21, 2018, 12:45:13 am »
It'll always return True because you're effectively doing this:

Code: Pascal  [Select][+][-]
  1.   If (Horizontal = True) and ((PosX+Length)<20) then
  2.     While (pX <= PosX+Length) do begin
  3.       {... No matter what happens here, then you do ...}
  4.       pX := pX + 1;
  5.       If (pX = PosX+Length) then
  6.         NoAdjacentElements := True;
  7.     end;
  8.  
  9.   If (Horizontal = False) and ((PosY+Length)<20) then
  10.     {The same happens, but with pY}

Note also that if the bounds check fail the Result is left undefined.

More notes: Rather than using conditions like "if (Horizontal = True)" or "if (Horizontal = False)", you can (and IMHO should) use "if Horizontal" and "if not Horizontal".

If you want, I can try a rewrite of the function to make it more concise, quicker and more ... "elegant". :)
« Last Edit: November 21, 2018, 12:54:09 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

WhatIsArrayPls

  • Newbie
  • Posts: 2
Re: Checking Adjacent Elements In 2D Array
« Reply #2 on: November 21, 2018, 02:42:41 am »
Please do, it would help me a lot. Got around the "always true" thing by adding

Code: Pascal  [Select][+][-]
  1. NoAdjacentElements := True;

Below PosY and PosX assignments and this second condition to both Whiles

Code: Pascal  [Select][+][-]
  1. (NoAdjacentElements = True)

Meaning it should stop as soon as it finds an adjacent element. After adding those two things, seems like it's doing it's job properly now.

I'll try to use "If Horizontal" and "If not Horizontal" too. "If Horizontal" would be the same as writing "If (Horizontal = True)", right?


jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Checking Adjacent Elements In 2D Array
« Reply #3 on: November 21, 2018, 03:12:31 am »
There is a shorter way..

At the beginning of code RESULT := false;

Then any checks you do like this..

  Result := (MyArray[someIndex] ='*') or Result;

 What this does is simply do a logical OR with an already existing results, there for you can
 use the same logic for each zone you test and if any of them are false it does not matter because
if RESULT is true from any of them it will remain TRUE at the end.
The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Checking Adjacent Elements In 2D Array
« Reply #4 on: November 21, 2018, 11:01:05 am »
Ok, here is some quick code (not an optimal version). I have assumed, from your code, that your "empty" value is '*'.

Code: Pascal  [Select][+][-]
  1. Function NoAdjacentElements(
  2.   Board: TwoDArray; pY, pX, Length: Integer; Horizontal:boolean): boolean;
  3.  
  4. var
  5.   Limit: integer;
  6.  
  7.   function TestOnY(Y, X: Integer): Boolean;
  8.   { Returns True if there's something other than '*'
  9.     either above or below Board[Y, X] }
  10.   begin
  11.     case Y of
  12.     1:  Result := Board[Y+1, X] <> '*';
  13.     20: Result := Board[Y-1, X] <> '*';
  14.     else
  15.       Result := (Board[Y+1, X] <> '*') or
  16.                 (Board[Y-1, X] <> '*');
  17.     end;
  18.   end;
  19.  
  20.   function TestOnX(Y, X: Integer): Boolean;
  21.   { Idem but checking to left and right }
  22.   begin
  23.     case X of
  24.     1:  Result := Board[Y, X+1] <> '*';
  25.     20: Result := Board[Y, X-1] <> '*';
  26.     else
  27.       Result := (Board[Y, X+1] <> '*') or
  28.                 (Board[Y, X-1] <> '*');
  29.     end;
  30.   end;
  31.  
  32.   function DoTests(Y, X: Integer): Boolean;
  33.   { Calls above tests and returns True if both failed,
  34.     i.e. if all above, below, left and right are '*'}
  35.   begin
  36.     Result := (not TestOnY(Y, X)) or
  37.               (not TestOnX(Y, X));
  38.   end;
  39.  
  40. Begin
  41.   { Ward against invalid parameters }
  42.   if (not (px in [1..20])) or (not (pY in [1..20])) then
  43.     raise ERangeError.Create('Invalid X or Y coordinate.');
  44.  
  45.   { Assume that there'll be adjacent elements ...}
  46.   Result := False;
  47.  
  48.   { and test against that assumption }
  49.   if Horizontal then begin
  50.     Limit := pX + Length;
  51.     if Limit < 20 then begin
  52.       repeat
  53.         Result := DoTests(pY, pX);
  54.         Inc(pX);
  55.       until Result or (pX > Limit)
  56.     end;
  57.   end else begin
  58.     Limit := pY + Length;
  59.     if Limit < 20 then begin
  60.       repeat
  61.         Result := DoTests(pY, pX);
  62.         Inc(pY);
  63.       until Result or (pY > Limit)
  64.     end;
  65.   end;
  66. end;
« Last Edit: November 21, 2018, 02:31:11 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018