ターミナルに Matrix が降ってくる Hack


1. ターミナルに雪を降らせるスクリプトというのがあるそうで

shell
ruby -e 'C=`stty size`.scan(/\d+/)[1].to_i;S=["2743".to_i(16)].pack("U*");a={};puts "\033[2J";loop{a[rand(C)]=0;a.each{|x,o|;a[x]+=1;print "\033[#{o};#{x}H \033[#{a[x]};#{x}H#{S} \033[0;0H"};$stdout.flush;sleep 0.1}'

2. 実行したらこうなるよ

※ ネタ元は ここの コメント欄らしいです

3. ruby の部分を取り出して、読みやすくリファクタしてみました

ruby
width = `stty size`.split(' ').last.to_i
positions = {}
puts "\033[2J" # clear screen
loop do
  positions[rand(width)] = 0
  positions.each { |column, row|
    print "\033[#{row};#{column}H " # erase snow
    positions[column] += 1
    print "\033[#{positions[column]};#{column}H❃" # draw snow
  }
  sleep 0.1
end

4. で、改造したくなりました

ruby
width = `stty size`.split(' ').last.to_i
positions = {}
print "\033[40m\033[32m" # black and green
puts "\033[2J" # clear screen
loop do
  positions[rand(width)] = 0
  positions.each { |column, row|
    positions[column] += 1
    print "\033[#{positions[column]};#{column}H#{[*' '..'z', *'ヲ'..'ン'].sample}"
  }
  sleep 0.1
end

5. ワンラインに戻すよ

shell
ruby -e 'w=`stty size`.split(" ").last.to_i;p={};print"\033[40m\033[32m\033[2J";loop{;p[rand(w)]=0;p.each{|c,r|;p[c]+=1;s=[*" ".."z",*"ヲ".."ン"].sample;print"\033[#{p[c]};#{c}H#{s}";};sleep 0.1}'

6. 実行したらこうなるよ

7. まとめ

タイトルはわざと頭悪そうにしてみました。釣りです 😐

8. おまけ

雪を多重スクロール化してみました。ターミナルをフルスクリーンにしてから実行してみてね

shell
ruby -e 'puts "\033[2J";Y,X=`stty size`.split(" ").map(&:to_i);z={"."=>1,"*"=>2,"❃"=>3};a=[];loop{a<<[rand(X),0,z.keys.sample];a.map{|b|;print "\033[#{b[1]};#{b[0]}H ";b[0]+=rand(3)-1;b[1]+=z[b[2]];print "\033[#{b[1]};#{b[0]}H#{b[2]}";b};a.reject!{|b|b[1]>Y};$stdout.flush;sleep 0.1}'

実行するとこう

コードはこう

ruby
height, width = `stty size`.split(' ').map(&:to_i)
z = { '.' => 1, '*' => 2, '❃' => 3 }
positions = []
puts "\033[2J" # clear screen
loop do
  positions << { x: rand(width), y: 0, z: z.keys.sample, i: 0 }
  positions.map { |position|
    print "\033[#{position[:y]};#{position[:x]}H " # erase snow
    position[:x] += rand(3) - 1
    position[:y] += z[position[:z]]
    print "\033[#{position[:y]};#{position[:x]}H#{position[:z]}" # draw snow
    position
  }
  positions.reject! { |snow| snow[:y] > height }
  sleep 0.1
end