Skip to content

Instantly share code, notes, and snippets.

@knsmr
Created March 8, 2011 06:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knsmr/859936 to your computer and use it in GitHub Desktop.
Save knsmr/859936 to your computer and use it in GitHub Desktop.
class BoardFactory
def self.create(text_or_state)
case text_or_state
when String
text = text_or_state
state = []
text.each_line do |l|
next if l =~ /^$/
state << l.chomp.split(//)
end
when Array
state = text_or_state
end
Board.new(state)
end
end
class Board
attr_accessor :height, :width, :state, :new_state
def initialize(state)
@state = state
@new_state = Marshal.load(Marshal.dump(@state))
@height = @state.size
@width = @state.map(&:size).max
visited_reset
end
def visited_reset
@visited = Array.new(@height) {Array.new(@width, "o")}
end
def remove
@state.each do |y|
y.map!{|c| c == "#" ? " ":c}
end
Board.new(@state)
end
def fall
new_line = []
@new_state = Array.new(@height) {Array.new(@width, " ")}
(0..(@width - 1)).each do |x|
(0..(@height - 1)).to_a.reverse.each do |y|
next if @state[y][x] == " "
new_line << @state[y][x]
end
(0..(@height - 1)).to_a.reverse.each do |y|
break if new_line.size == 0
@new_state[y][x] = new_line.shift
end
end
Board.new(@new_state)
end
def all_delete
(0..(@height - 1)).each do |y|
(0..(@width - 1)).each do |x|
delete(y, x)
end
end
if !@new_state.flatten.include?("#")
nil
else
Board.new(@new_state)
end
end
private
def delete(y, x)
return if @state[y][x] == "#"
same = find_same(y, x, [])
visited_reset
if same.size >= 4
same.each do |pos|
@new_state[pos[0]][pos[1]] = "#"
end
end
end
def find_same(y, x, pos)
pos << [y, x]
@visited[y][x] = "."
col = @state[y][x]
return pos if col == " "
if (y > 0) && (@visited[y - 1][x] != ".") && (@state[y - 1][x] == col)
find_same(y - 1, x, pos)
end
if (y < @height - 1) && (@visited[y + 1][x] != ".") && (@state[y + 1][x] == col)
find_same(y + 1, x, pos)
end
if (x > 0) && (@visited[y][x - 1] != ".") && (@state[y][x - 1] == col)
find_same(y, x - 1, pos)
end
if (x < @width - 1) && (@visited[y][x + 1] != ".") && (@state[y][x + 1] == col)
find_same(y, x + 1, pos)
end
pos
end
def to_s
@state.inject(""){|s, l| s += ((l.join) + "\n")} + "-" * @width
end
end
b = Board.new(File.open(ARGV.shift).read)
rensa = 0
p b; sleep 1
loop do
b = b.all_delete
break if b.nil?
p b; sleep 0.3
b = b.remove
p b; sleep 0.3
b = b.fall
p b; sleep 0.3
rensa += 1
end
b = BoardFactory.create(File.open(ARGV.shift).read)
rensa = 0
p b; sleep 1
loop do
b = b.all_delete
break if b.nil?
p b; sleep 0.3
b = b.remove
p b; sleep 0.3
b = b.fall
p b; sleep 0.3
rensa += 1
end
print "rensa: #{rensa}\n"
% ruby puyo.rb p2.txt
GYRR
RYYGYG
GYGYRR
RYGYRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
GYRR
R##GYG
G#GYRR
R#GYRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
GYRR
R GYG
G GYRR
R GYRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
YRR
R GGYG
G GYRR
R GYRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
YRR
R ##YG
G #YRR
R #YRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
YRR
R YG
G YRR
R YRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
RR
R YYG
G YRR
R YRG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
RR
R ##G
G #RR
R #RG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
RR
R G
G RR
R RG
YGYRYG
GYRYRG
YGYRYR
YGYRYR
YRRGRG
RYGYGG
GRYGYR
GRYGYR
GRYGYR
------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment