🙌

# 2次元フィールドをオブジェクトで表現する

2021/07/03に公開

## 実装

<<~NOTE
c	c	c W
r	0	1	2
r	3	4	5
r	6	7	8
H
NOTE
class Field

def initialize(h, w, init_val = nil)
@height = h
@width = w
@field = Array.new(h * w, init_val)
end

def get(r, c)
return nil if r < 0 || c < 0
return nil if r >= height || c >= width

@field[pos(r, c)]
end
alias [] get

def get!(r, c)
raise if r < 0 || c < 0
raise if r >= height || c >= width

@field[pos(r, c)]
end

def set(r, c, val)
return false if r < 0 || c < 0
return false if r >= height || c >= width

@field[pos(r, c)] = val

true
end

def set!(r, c, val)
set(r, c, val) || raise
end
alias []= set!

def row(r)
@field[r*width, width]
end

def col(c)
arr = []
while (c < width * height)
arr << @field[c]

c += width
end

arr
end

def rows
Enumerator.new do |y|
height.times do |r|
y << row(r)
end
end
end

def cols
Enumerator.new do |y|
width.times do |c|
y << col(c)
end
end
end

def dump
@field.each_slice(width){|a| p a }
end

private

def pos(r, c)
r * width + c
end
end

## example

H = 10
W = 4
field = Field.new(H, W, 0)

H.times do |r|
W.times do |c|
field.set(r, c, (r + c)**2)
end
end

field[3, 0] = 1000
puts field[3, 0]

field.dump

p field.row(0)
p field.row(3)
p field.col(0)
p field.col(1)

field.rows.each do |row|
puts row.sum
end

field.cols.each do |col|
puts col.sum
end