Prev: Cpp Complier
Next: bug in TkComm::list?
From: w_a_x_man on 15 Jul 2010 06:49 On Jul 14, 6:07 pm, w_a_x_man <w_a_x_...(a)yahoo.com> wrote: > 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 def get2d ary, x, y if ary[y] ary[y][x] else nil end end ary = [ %w(Z Z Z Z), %w(Z H H Z), %w(Z X Z Z) ] puts get2d( ary,2,1 ) puts get2d( ary,1,2 ) puts get2d( ary,3,3 ) puts get2d( ary,4,0 ) --- output --- H X nil nil
From: w_a_x_man on 15 Jul 2010 10:32 On Jul 15, 5:49 am, w_a_x_man <w_a_x_...(a)yahoo.com> wrote: > On Jul 14, 6:07 pm, w_a_x_man <w_a_x_...(a)yahoo.com> wrote: > > > 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 > > def get2d ary, x, y > if ary[y] > ary[y][x] > else > nil > end > end > > ary = [ > %w(Z Z Z Z), > %w(Z H H Z), > %w(Z X Z Z) ] > > puts get2d( ary,2,1 ) > puts get2d( ary,1,2 ) > puts get2d( ary,3,3 ) > puts get2d( ary,4,0 ) > > --- output --- > H > X > nil > nil def get2d ary, x, y if ![x,y].include?(-1) and ary[y] ary[y][x] else nil end end ary = [ %w(Z Z Z Z), %w(Z H H Z), %w(Z X Z Z) ] puts get2d( ary,2,1 ) puts get2d( ary,1,2 ) puts get2d( ary,3,3 ) puts get2d( ary,4,0 ) puts get2d( ary,4,-1 ) --- output --- H X nil nil nil
From: Shawn W_ on 15 Jul 2010 17:45 Dave Howell wrote: > 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. Just be aware I'm a complete newb at programing and Ruby, so the more elegant the code, the harder it is for me to read. David, I tried your solution but it still falls over. Don't you need to specify what happens if y<0 or y>(@height-1) is the case? I tried... if y<0 or y>(@height-1) nil else @data[x][y] = value end ...but that didn't work? It falls over the moment it looks north from the top row, or looks south east from the bottom row. Also, I understand the line... deltaX, deltaY = *Delta[z] ...is allocating the Delta array values to the deltaX and deltaY variables based on the direction z given, but what is the * symbol doing? By the way, my program uses a hex grid, not a square grid - I posted a square grid just for clarity. Adjacent cells directions change for odd and even rows on a hex grid, but I think I can just create two Delta arrays (Delta_even and Delta_odd) and modify the 1,0,-1 values for each, then check for odd/eveness in y. I have yet to nut out the other solution but will go through it later today. -- Posted via http://www.ruby-forum.com/.
From: Shawn W_ on 16 Jul 2010 01:41 Okay, just found out that... @data[x][y] unless y<0 or y>@height ...is the same as stating nil anyway, according to http://www.themomorohoax.com/2009/05/21/when-to-use-nil-in-ruby-methods The error I'm getting is... undefined method `[]=' for nil:NilClass (NoMethodError) ...when the program hits this part of the code... Array2D[x,y,1] = "X " -- Posted via http://www.ruby-forum.com/.
From: Martin DeMello on 16 Jul 2010 04:24
On Fri, Jul 16, 2010 at 11:11 AM, Shawn W_ <shawnw(a)internode.on.net> wrote: > Okay, just found out that... > > @data[x][y] unless y<0 or y>@height > > ...is the same as stating nil anyway, according to > http://www.themomorohoax.com/2009/05/21/when-to-use-nil-in-ruby-methods > > The error I'm getting is... > > undefined method `[]=' for nil:NilClass (NoMethodError) > > ...when the program hits this part of the code... > > Array2D[x,y,1] = "X " The basic problem is that ruby doesn't have rectangular arrays, you have to use arrays of arrays. So "array[y][x]" means "get array[y] (which is itself an array) and take the xth element of that". So let's say you initialize your array to [4][3]. Then you have array = [ [nil, nil, nil], # array[0] [nil, nil, nil], # array[1] [nil, nil, nil], # array[2] [nil, nil, nil] # array[3] ] Now say you set array[1][2] = "X". Your new array is array = [ [nil, nil, nil], # array[0] [nil, nil, X ], # array[1] [nil, nil, nil], # array[2] [nil, nil, nil] # array[3] ] you can do this either via array[1][2] = "X" or a = array[1] a[2] = "X" So what happens when you go off the end of the array? Calling array[n] where n is out of bounds will return nil, as expected... array[1][100] # => nil which is equivalent to a = array[1] #=> [..., ..., ...] a[100] #=> nil But if you go out of bounds in the other dimension array[100][1] # => undefined method `[]=' for nil:NilClass (NoMethodError) because what you're in effect doing is a = array[100] #=> nil a[1] # => trying to call [] on nil, which raises the error martin |