GUIのフロントエンドから、コアとなるCUIプログラムを制御して、GUIでオセロロジックを動かしてみます。
マウスをクリックしたら、GUIフロントエンドは、CUIプログラムへ標準入力でコマンドを送ります。
CUIプログラムは受け取った座標を判定し、GUIフロントエンドへ石の表示コマンドを送ります。
Tcl/Tkで作られたフロントエンドからCUIプログラムへは、標準入出力でやりとりするため、openコマンドで、パイプをオープンします。
set pipe [open “| ./a.out” r+]
オープン後getsコマンドを使い、CUIプログラムからの文字列を一行ずつ読みこみます。
gets $pipe 受け取った文字列
CUIプログラムへ文字列を送信するには、putsコマンドで行います。
puts $pipe 送る文字列
では、「tcl/tkで黒と白」で作成したGUIプログラムを改造したソースです。
CUIプログラムから結果を受け取ると、update_borad関数でオセロボードの更新を行います。
first_char==”Y”という判定がありますが、CUIプログラムの、YOUという催促の、最初の文字Yで、結果通知の完了トリガとしています。
1 proc update_board { pipe } { 2 while {[gets $pipe str] >= 0} { 3 set first_char [string range $str 0 0] 4 5 if { $first_char == "Y" } { ;# Y in YOU 6 break 7 } 8 9 set dst [split $str ","] 10 set xy [lindex $dst 0] 11 set bw [lindex $dst 1] 12 if {$bw == "B"} { 13 .b$xy configure -text "●" -fg black 14 } else { 15 .b$xy configure -text "●" -fg white 16 } 17 } 18 } 19 20 set pipe [open "| ./a.out" r+] 21 22 set turnsw 0 23 for {set i 1} {$i <= 8} {incr i} { 24 for {set j 1} {$j <= 8} {incr j} { 25 button .b$i$j -font {FreeMono 40 bold} -bg green -activebackground yellow -activeforeground red 26 grid .b$i$j -in . -row $i -column $j -sticky nsew 27 grid columnconfigure . {1 2 3 4 5 6 7 8} -weight 1 -minsize 60 28 grid rowconfigure . {1 2 3 4 5 6 7 8} -weight 1 -minsize 60 29 30 bind .b$i$j <Enter> { 31 %W configure -bg red 32 } 33 bind .b$i$j <Leave> { 34 %W configure -bg green 35 } 36 bind .b$i$j <Button> { 37 set x [string range %W 2 2] 38 set y [string range %W 3 3] 39 puts $pipe "$x,$y\n";flush $pipe 40 41 update_board $pipe 42 43 set turnsw [expr 1 - $turnsw] 44 } 45 } 46 } 47 48 update_board $pipe
実行してみましょう。
takk@deb83:~$ git clone https://github.com/takkete/scrap.git takk@deb83:~$ cd scrap takk@deb83:~$ cd scrap takk@deb83:~/scrap$ gcc reversi.c takk@deb83:~/scrap$ wish reversi.tcl
下のような緑のマトリクスが表示されて、マウスクリックした箇所に白と黒を交互に置石できると思います。
コメント
[…] 「GUIプログラムからCUIプログラムを使う(標準入出力)」で作ったオセロのGUIフロントエンドを、将棋でも使えるように変更してみます。 shogi.tclではなく、gameboard.tclとしたのは、マス目がある他のゲームにも対応するためです。 […]