From: Shawn W_ on
I have a 2D Array. I have written a method
Array2D.adjacent(x,y,direction) that returns the adjacent cell to x,y in
the direction given. How do I deal with the boundary conditions without
receiving an error message.

For example, if I refer to a cell on the top row, and look north there
will be nothing there, and my program falls over.

I will be creating methods that run over the whole 2D array, replacing
things in random directions, so when it randomly hits a boundary I need
my program to ignore cells outside the boundary.

How can I do this? Thx
--
Posted via http://www.ruby-forum.com/.

From: w_a_x_man on
On Jul 14, 3:56 pm, Shawn W_ <sha...(a)internode.on.net> wrote:
> I have a 2D Array. I have written a method
> Array2D.adjacent(x,y,direction) that returns the adjacent cell to x,y in
> the direction given. How do I deal with the boundary conditions without
> receiving an error message.
>
> For example, if I refer to a cell on the top row, and look north there
> will be nothing there, and my program falls over.
>
> I will be creating methods that run over the whole 2D array, replacing
> things in random directions, so when it randomly hits a boundary I need
> my program to ignore cells outside the boundary.
>
> How can I do this? Thx
> --
> Posted viahttp://www.ruby-forum.com/.

Yields nil if out of bounds:

if ary[y]
ary[y][x]
else
nil
end
From: Shawn W_ on
Thx. Don't quite understand that code. I tried plugging in some nils but
didn't work. Do I just need to assign nil values to the cells outside
the bounds of my array for the program to ignore them?

Here's what I've got so far. At the moment everything is wrapping. I
need it to wrap left and right, but to be capped top and bottom.

class Array2D

attr_accessor :width, :height

def initialize(width, height)
@width = width
@height = height
@data = Array.new(@width) { Array.new(@height) }
end

# Returns adjacent cell of given 2D array index x,y, in the given
direction z, where z = 0 is no direction (the cell in the middle), and z
= 1-8 are the surrounding cells.
def [](x, y, z)
x = x % @width # modulus % allows wrapping
y = y % @height
if z == 0
@data[x][y]
elsif z == 1
@data[x][y+1]
elsif z == 2
@data[x+1][y+1]
elsif z == 3
@data[x+1][y]
elsif z == 4
@data[x+1][y-1]
elsif z == 5
@data[x][y-1]
elsif z == 6
@data[x-1][y-1]
elsif z == 7
@data[x-1][y]
elsif z == 8
@data[x-1][y+1]
end
end

# Allows the allocation of values to adjacent cell of given 2D array
index x,y, in the given direction z, where z = 0 is no direction (the
cell in the middle), and z = 1-8 are the surrounding cells.
def []=(x, y, z, value)
x = x % @width # modulus % allows wrapping
y = y % @height
if z == 0
@data[x][y] = value
elsif z == 1
@data[x][y+1] = value
elsif z == 2
@data[x+1][y+1] = value
elsif z == 3
@data[x+1][y] = value
elsif z == 4
@data[x+1][y-1] = value
elsif z == 5
@data[x][y-1] = value
elsif z == 6
@data[x-1][y-1] = value
elsif z == 7
@data[x-1][y] = value
elsif z == 8
@data[x-1][y+1] = value
end
end

end

# This method replaces contents of 9 cells in a square configuration
at a random location on the 2D array.
def form_plates
x = rand(@cols)
y = rand(@rows)
Array2D[x,y,0] = "X "
Array2D[x,y,1] = "X "
Array2D[x,y,2] = "X "
Array2D[x,y,3] = "X "
Array2D[x,y,4] = "X "
Array2D[x,y,5] = "X "
Array2D[x,y,6] = "X "
Array2D[x,y,7] = "X "
Array2D[x,y,8] = "X "
end
--
Posted via http://www.ruby-forum.com/.

From: Shawn W_ on
A better way to describe it.

Here's a 16 x 8 array of Z's, with the Z replaced with X and H's like
so:

Array2D[6,3,0] = "X "
Array2D[6,3,1] = "H " # direction 1 (north) from array index 6,3
Array2D[6,3,2] = "H " # direction 2 (north east) from array index 6,3
Array2D[6,3,3] = "H "
Array2D[6,3,4] = "X "
Array2D[6,3,5] = "X "
Array2D[6,3,6] = "X "
Array2D[6,3,7] = "X "
Array2D[6,3,8] = "X "

Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z X H H Z Z Z Z Z Z Z Z
Z Z Z Z Z X X H Z Z Z Z Z Z Z Z
Z Z Z Z Z X X X Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z


What I need is Array2D[6,0,1] = "H ", for example, not to make my
program fall over (array index 6,0 in direction 1 (north) sits outside
my array).

At the moment it wraps top and bottom like so:

Z Z Z Z Z X X H Z Z Z Z Z Z Z Z
Z Z Z Z Z X X X Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z X H H Z Z Z Z Z Z Z Z

If I remove the top/bottom wrapping, I need it to just cut it off at the
top, like so:

Z Z Z Z Z X X H Z Z Z Z Z Z Z Z
Z Z Z Z Z X X X Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
--
Posted via http://www.ruby-forum.com/.

From: Dave Howell on
I was going to suggest using the 'case' statement instead of all those elsifs, but then I realized there was an even better way.

class Array2D

Delta=[[0,0], [0,1], [1,1], [1,0], [1,-1], [0,-1], [-1,-1], [-1,0], [-1,1]]
attr_reader :width, :height

def initialize(width, height)
@width = width
@height = height
@data = Array.new(@width) { Array.new(@height) }
end

def [](x, y, z)
deltaX, deltaY = *Delta[z]
x = x + deltaX % @width
y = y + deltaY
@data[x][y] unless y<0 or y>@height
end

def []=(x, y, z, value)
deltaX, deltaY = *Delta[z]
x = (x + deltaX) % @width # modulus % allows wrapping
y = y + deltaY
@data[x][y] = value unless y<0 or y>(@height-1)
end
end


Obviously the Delta array takes the place of the elsif chains in both [] and []=. Also, :width and :height are defined with attr_reader, not attr_accessor, since it doesn't do any good at all to change those values after the array has been created.
 |  Next  |  Last
Pages: 1 2 3 4 5
Prev: Cpp Complier
Next: bug in TkComm::list?