Ruby/Tkを使ってBrainf*ckのプログラムを可視的にしてみた

#はじめに
前回[brainf*ckの記事](http://qiita.com/sugunisu/items/cd93b849dc1dfe21ce52)について書いてみたわけだが
文字だけだとわからないと思うので
ビジュアル的にプログラムが動いている様子がわかるプログラムを書くついでにRuby/Tkについて勉強してみた

#Ruby/Tkのインストール
Windowsの環境についてだけ説明します(他のOSはほかの記事を参考にしてみてください)
今回確認したrubyのバージョンは2.3です
1. ActiveTclを[このサイト](http://www.activestate.com/activetcl)からダウンロード,インストールします**(このとき最新版の8.6ではなく,8.5.18.0をインストールすることに注意してください)**
2. Rubyをインストールします,既にインストールしている人もそうでない人もRubyインストーラを起動して**「Tcl/Tkサポートをインストールする」にチェックを付けてインストールすればOK**みたいです

#実際に動かしてみる
```ruby:test.rb
# 1
require 'tk'

# 2
test_btn = TkButton.new{
  text 'test'
  command { exit }
  pack
}

# 3.
Tk.mainloop
```
##実行結果
![testwindow.png](https://qiita-image-store.s3.amazonaws.com/0/152328/84a85cfd-295b-58a5-aabf-b8cf3e4d0736.png)
このようなウィンドウがでてきて,ボタンを押すと消えます
##軽く解説
1. ruby/tkを動かすためにはtkをrequireする必要があります
2. ここでコンポーネントを配置していきます.ここではtest_btnというボタンを「"test"という文字」で「押すと終了する」ように作ってます.最後にpackで配置します
3. 最終行にTk.mainloopと書くことで毎ループ動くことになります

#そんな感じで作ったのがこちら
```ruby:brainfuck.rb
require 'tk'

#### SUMMARY ###############################################
##                                                         #
## array a is the stack values in i th command             #
## and let p denote the pointer where the operating stack, #
## which is shown with red background in the GUI           #
## str written in sourcel is a command in "main.bf"        #
## and str2 shows the point which is p visibly             #
##                                                         #
############################################################

a=[0,0,0,0,0,0,0,0]
str ="+++-->>+<+++[>+<-]>>>[>+<-]x"
str2="^                           "
i=0
p=0
branket_stack=[]


#### Winodow area ####

window = TkRoot.new{
  title 'Brainf*ck Visualizer'
  resizable [0,0]

}

#### Registers area ####

regf = TkFrame.new{
  relief 'sunken'
  borderwidth 3
  padx 15
  pady 20
  pack('side' => 'top')  
}


f=[]
l=[]
8.times do |n|
  f << TkFrame.new(regf){
    relief 'sunken'
    borderwidth 2
    background ((p==n)?"red":"gray")
    padx 10
    pady 10
    pack('side' => 'left')
  }
  l << TkLabel.new(f[n]){
  text a[n]
  pack
  }
end

#### Script Area ####

scriptf = TkFrame.new(){
  pack('side' => 'top')

}

sourcel = TkLabel.new(scriptf){
  text str + "\n" + str2
  font TkFont.new("family"=>"MS Mincho", "size"=>10)
  pack('side' => 'left')
}

load_btn = TkButton.new{
  text 'load'
  command {
    a.map!{0}
    p=0
    i=0
    str=IO.read('main.bf')
    str+='x'
    str2=(str.size).times.map{" "}.join
    str2[0]='^'
    sourcel.text = str + "\n" + str2
    8.times do |n|
      l[n].text=a[n]
      f[n].background ((p==n)?"red":"gray")
    end
  }
  pack
}

next_btn = TkButton.new{
  text 'next'
  command proc{
    if i==str.size
      exit
    else
      case str[i]

        when '+'
          a[p]+=1
          str2[i]=' '
          i+=1
          str2[i]='^'
          sourcel.text = str + "\n" + str2
          8.times do |i|
            l[i].text = a[i]
          end

        when '-'
          a[p]-=1
          str2[i]=' '
          i+=1
          str2[i]='^'
          sourcel.text = str + "\n" + str2
          8.times do |i|
            l[i].text = a[i]
          end

        when '>'
          f[p].background="gray"
          p+=1
          f[p].background="red"
          str2[i]=' '
          i+=1
          str2[i]='^'
          sourcel.text = str + "\n" + str2
          8.times do |i|
            l[i].text = a[i]
          end

        when '<'
          f[p].background="gray"
          p-=1
          f[p].background="red"
          str2[i]=' '
          i+=1
          str2[i]='^'
          sourcel.text = str + "\n" + str2
          8.times do |i|
            l[i].text = a[i]
          end

        when '['
          if a[p] == 0
            while str[i]!=']'
              i+=1
            end
          else
            branket_stack << i
            i+=1
          end
          str2=(str.size).times.map{" "}.join
          str2[i]='^'
          sourcel.text = str + "\n" + str2

        when ']'
          if a[p] == 0
            branket_stack.pop
            i+=1
          else
            i=branket_stack.pop
          end
          str2=(str.size).times.map{" "}.join
          str2[i]='^'
          sourcel.text = str + "\n" + str2
      end
      
    end
 }
  pack
}

Tk.mainloop
```
##実行イメージ
![bfv.png](https://qiita-image-store.s3.amazonaws.com/0/152328/7eea21bf-3ff9-6f05-6bd9-e67917f4bf28.png)
このように今あるポインタとメモリ内の数字を見ながらワンステップずつ実行できます
また,loadボタンを押すことにより同じフォルダに保存したbrainf*ckのファイル"main.bf"を読み込むことができます
いつものことながら適当にしか作ってないので,メモリは8個という前提で[ ]の数合わせも確認しません,"."や","にも対応しません...
気が向いたら訂正します