Prev: Cpp Complier
Next: bug in TkComm::list?
From: Shawn W_ on 14 Jul 2010 16:56 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 14 Jul 2010 19:07 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 14 Jul 2010 21:04 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 15 Jul 2010 04:26 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 15 Jul 2010 05:23
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. |