Skip to content

Commit

Permalink
feature: Erase lines.
Browse files Browse the repository at this point in the history
  • Loading branch information
ledsun committed Dec 31, 2023
1 parent 56350af commit fb4fd5d
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 17 deletions.
41 changes: 26 additions & 15 deletions lib/field.rb
@@ -1,4 +1,5 @@
require_relative 'field/wall'
require_relative 'field/row'

# ゲームの盤面を表すクラス
class Field
Expand All @@ -7,15 +8,7 @@ class Field
WIDTH = 12

def initialize
@grid = Array.new(HEIGHT) do |y|
Array.new(WIDTH) do |x|
if wall?(x, y)
Wall.new(x, y)
else
Cell.new(x, y)
end
end
end
@grid = Array.new(HEIGHT) { |y| Row.new(y, WIDTH) }
end

# フィールドのブロックを一つずつ処理します。
Expand All @@ -34,22 +27,40 @@ def add_block(block)
end

def paint(color)
cells_each do |cell|
cell.paint color
end
cells_each { |cell| cell.paint color }
end

private
def clear_lines!
# フィールドの上から順番に行を見ていく
in_field_rows.each do |row|
# 行が揃っているかを判定する
next unless row.filled?

# 揃っていたらその行を消す
row.clear!

# 揃った行のひとつ上の行から昇順に、その行のブロックを下に落としていく
@grid.slice(1, row.y).reverse_each do |upper_row|
upper_row.down_cells self
end
end
end

def wall?(x, y)
x == 0 || x == 11 || y == 0 || y == 21
def down_cell_of(cell)
self[cell.y + 1, cell.x]
end

private

def cells_each
@grid.each do |row|
row.each do |cell|
yield cell
end
end
end

def in_field_rows
@grid.select { |row| row.is_in_field }
end
end
27 changes: 26 additions & 1 deletion lib/field/cell.rb
Expand Up @@ -4,7 +4,7 @@
# セルにブロックがあると、四角を表示します。
# ブロックの色が指定できます。
class Cell
attr_accessor :block
attr_reader :x, :y, :block

def initialize(x, y)
@x = x
Expand All @@ -14,4 +14,29 @@ def initialize(x, y)
def paint(color)
@block = Block.new(color, @x, @y)
end

def down_block(field)
return unless @block

field.down_cell_of(self).recieve_block_from(self)
end

def recieve_block_from(other)
raise 'other cell has no block' unless other.block

@block = Block.new(other.block.color, @x, @y)
other.block = nil
end

def block=(block)
raise "position is not match" unless match_position?(block)
@block = block
end

private

def match_position?(block)
return true unless block
block.x == @x && block.y == @y
end
end
39 changes: 39 additions & 0 deletions lib/field/row.rb
@@ -0,0 +1,39 @@

# ゲームの盤面の一行を表すクラス
class Row
include Enumerable

attr_reader :is_in_field, :y

def initialize(y, width)
@y = y
@cells = Array.new(width) do |x|
if wall?(x, y)
Wall.new(x, y)
else
Cell.new(x, y)
end
end
@is_in_field = !wall?(1, y)
end

def filled?
@cells.all? { |cell| cell.block }
end

def clear!
in_field_cells.each { |cell| cell.block = nil }
end

def down_cells(field)
in_field_cells.each { |cell| cell.down_block(field) }
end

def [](x) =@cells[x]
def each = @cells.each { |cell| yield cell }

private

def in_field_cells = @cells.reject { |cell| cell.is_a? Wall }
def wall?(x, y) = x == 0 || x == 11 || y == 0 || y == 21
end
5 changes: 4 additions & 1 deletion lib/game.rb
Expand Up @@ -29,8 +29,11 @@ def run
# テトリミノを更新
@tetorimino.update(input)

# テトリミノが着地したら新しいテトリミノを生成
# テトリミノが着地したら
if @tetorimino.landed?
# 行が揃ったら消す
@field.clear_lines!
# 新しいテトリミノを生成
@tetorimino = Tetorimino.create(@field)
# ゲームオーバー判定
next game_over! if game_over?
Expand Down

0 comments on commit fb4fd5d

Please sign in to comment.