From: Dave Howell Date: 2010-07-22T15:37:20+09:00 Subject: Re: Return nothing when looking outside the bounds of 2D array? On Jul 18, 2010, at 20:47 , Shawn W_ wrote: > > > > However, it still falls over when I try to insert the above into my main > program, as below: > > > def insert_teleporting_square > m = rand(@cols) > n = rand(@rows) > @world[m,n,0]["hex_id_A"] = "A " > @world[m,n,1]["hex_id_A"] = "H " > @world[m,n,2]["hex_id_A"] = "H " > @world[m,n,3]["hex_id_A"] = "H " > @world[m,n,4]["hex_id_A"] = "A " > @world[m,n,5]["hex_id_A"] = "A " > @world[m,n,6]["hex_id_A"] = "A " > @world[m,n,7]["hex_id_A"] = "A " > @world[m,n,8]["hex_id_A"] = "A " > end > > > > It falls over when it hits one of these two lines: > @world[m,n,1]["hex_id_A"] = "H " > @world[m,n,4]["hex_id_A"] = "A " > > With error as before: > undefined method `[]=' for nil:NilClass (NoMethodError) > > What my program does is generate an array, then populates each cell of > that array with a hash. It looks like when it tries to access the hash > values outside the array boundary it runs into problems? Do I need > another method inside the Array2D class to deal with hash access? If so, > how can this be done? If not, can anyone see any other reason for the > error? > I think I got it. I did away with storing my cell data in a hash; rather > I will put an array in each cell of the 2D array, and add another > parameter to the def [] and def []= methods to access it. Forgive me, but this looks like you're just being too lazy, and your code's starting to really suffer. Instead of trying to make it work no matter how much stuff you throw at the array, start checking to make sure that you're not doing something illegal or irrational before trying to do it. >> a[3,3,2] => "-" >> a[4,3,2] => nil Because a[5,1] is out of bounds So >>a[3,3,2]="Q" =>"Q" >> a[4,3,2]="Q" => undefined method `[]=' for nil:NilClass (NoMethodError) Because that's like saying nil="Q" One way you could check would be @world[m,n,1]["hex_id_A"] = "H " if @world[m,n,1] Or, to put it in context: def insert_teleporting_square m = rand(@cols) n = rand(@rows) (0..8).each {|index| @world[m,n,index]["hex_id_A"] = "A " if @world[m,n,index]} (1..3).each {|index| @world[m,n,index]["hex_id_A"] = "H " if @world[m,n,index]} end Here's another way: class HexArray def neighbors(x,y) (1..6).collect{|index| index if self[x,y,index]}.compact end end >> a = HexArray.new(5,5) >> a.neighbors(2,2) => [1, 2, 3, 4, 5, 6] >> a.neighbors(4,4) => [1, 5, 6] >> a.neighbors(2,2).each{|n| a[2,2,n]="x"} => [1, 2, 3, 4, 5, 6] >> a.neighbors(4,4).each{|n| a[4,4,n]="y"} => [1, 5, 6] >> a - - - - - - x x - - - x - x - - x x y y - - - y -