```On Jul 15, 2010, at 14:45 , Shawn W_ wrote:

> Dave Howell wrote:
>> I was going to suggest using the 'case' statement instead of all =
those=20
>> elsifs, but then I realized there was an even better way.
>>=20
>> class Array2D
>>=20
>>  Delta=3D[[0,0], [0,1], [1,1], [1,0], [1,-1], [0,-1], [-1,-1], =
[-1,0],=20
>> [-1,1]]
>>=20
>>  def initialize(width, height)
>>    @width =3D width
>>    @height =3D height
>>    @data =3D Array.new(@width) { Array.new(@height) }
>>  end
>>=20
>>  def [](x, y, z)
>>    deltaX, deltaY =3D *Delta[z]
>>    x =3D x + deltaX % @width
>>    y =3D y + deltaY
>>    @data[x][y] unless y<0 or y>@height
>>  end
>>=20
>>  def []=3D(x, y, z, value)
>>    deltaX, deltaY =3D *Delta[z]
>>    x =3D (x + deltaX) % @width # modulus % allows wrapping
>>    y =3D y + deltaY
>>    @data[x][y] =3D value unless y<0 or y>(@height-1)
>>  end
>> end
>>=20
>>=20
>> Obviously the Delta array takes the place of the elsif chains in both =
[]=20
>> and []=3D. Also, :width and :height are defined with attr_reader, not=20=

>> attr_accessor, since it doesn't do any good at all to change those=20
>> values after the array has been created.
>=20
> Just be aware I'm a complete newb at programing and Ruby, so the more=20=

> elegant the code, the harder it is for me to read.

Well, for what it's worth, it could have been 'eleganted' far more =

> David, I tried your solution but it still falls over. Don't you need =
to=20
> specify what happens if y<0 or y>(@height-1) is the case? I tried...
>=20
>    if y<0 or y>(@height-1)
>        nil
>      else
>        @data[x][y] =3D value
>    end
>=20
> ...but that didn't work? It falls over the moment it looks north from=20=

> the top row, or looks south east from the bottom row.

As you've discovered, "unless" is the same as "if not", and=20

(result) if (test)=20

is the same as

if (test) then
(result)
else
nil
end

Note that you can also do=20

(result)
else
nil
end

which is the same as

if (test) then
else
end

So, putting it all together, you could say

If (test) is true, myAnswer will get (result). If it's not true, it will =
get nil.

>=20
> Also, I understand the line...
>=20
> deltaX, deltaY =3D *Delta[z]
>=20
> ...is allocating the Delta array values to the deltaX and deltaY=20
> variables based on the direction z given, but what is the * symbol=20
> doing?

Splitting the array into pieces. Except that when I tested it just now, =
it's apparently unnecessary. I didn't know that!

> By the way, my program uses a hex grid, not a square grid - I posted a=20=

> square grid just for clarity. Adjacent cells directions change for odd=20=

> and even rows on a hex grid, but I think I can just create two Delta=20=

> arrays (Delta_even and Delta_odd) and modify the 1,0,-1 values for =
each,=20
> then check for odd/eveness in y.

I've worked with hex grids before. You don't need a pair of arrays, you =
can model a hex grid with a normal 2-d array.=20

Hex: 0=3Dsame, 1 =3D upper right, 2 =3D right, 3 =3D lower right, 4 =3D =
lower left, 5 =3D left, 6 =3D upper left, with [0,0] in the upper left =
of the grid.

Delta=3D[[0,0], [0.5,-1], [1,0], [0.5,1], [-0.5,1], [-1,0], =
[-0.5,-1]]

If you're in an odd row (y%2 =3D=3D1), then add 0.75 to x. If you're in =
an even row, add 0.25. Then drop the decimal part to get your x,y =
values.

x =3D (x + deltaX + 0.25 + (0.5 if y%2 =3D=3D1).to_f).to_i

The ".to_f" is needed because if y%2 is NOT =3D=3D 1, the result is =
"nil", and you can't add nil to a number, so the .to_f converts 'nil' to =
"0.0".=20

Imagine each co-ordinate is a brick in a normal wall of bricks. Every =
other row is slid over a bit, so you have to zig-zag in order to go =
'straight down" the wall. You might need to play around with it to see =
why it works . . .

> The error I'm getting is...
>=20
> undefined method `[]=3D' for nil:NilClass (NoMethodError)
>=20
> ...when the program hits this part of the code...
>=20
> Array2D[x,y,1] =3D "X "

I don't consider myself a hard-core Ruby expert, so I wouldn't be =
surprised if there was a bug in my code. On the other hand, I'll bet =
part of the problem is that you appear to be confusing a Class with an =
instance. You can't (or shouldn't normally be able to) assign anything =
to "Array2D".=20

myTerritory =3D Array2D.new
myTerritory[3,4,1] =3D "X "

enemyTerritory =3D Array2D.new
enemyTerritory[2,3,1] =3D "X "

Now, it *is* possible to define Array2D in a way that would let you say =
something like Array2D[x,y,1] =3D "X " and have it work, but we haven't =
done that here and I don't think you want to. There are . . . =
ramifications . . .=

```