課題

もくじ
グラフデータファイルの仕様
ここでは,この課題で折れ線グラフのデータを格納する「グラフデータファイル」の仕様について説明します. まず例を示します.
237 26 61 2 8 18 16 21 24 28 32 39 : : : :
グラフデータファイルの仕様は次の通りです.
- 第1行
4つの整数(R,G,B,W)が空白で区切られて並んでいる. それらは描画する折れ線の色と幅を次のように定めている.
R グラフの描画色の赤成分 (0≦R≦255) G グラフの描画色の緑成分 (0≦G≦255) B グラフの描画色の青成分 (0≦B≦255) W グラフの線の幅 (W≧1) - 第2行以降
各行に2つの整数が空白で区切られて並んでいる. それらがグラフ上の点(xi,yi)を順に定めている(i=0,1,2,...).点の座標はタートルグラフィクスのキャンバスの座標系の値としてそのまま扱う. これらの点を順につないで折れ線を描く.
備考
- グラフ上の点の個数のデータはグラフデータファイルには含まれていません.
- グラフデータファイル内で指定された点がキャンバス内に入っているかどうかは考慮しなくて構いません.あくまでも指定された通りに描画するようにします.
- グラフデータファイルは常に正しい書式で記述されていると仮定して構いません. 書式が誤っている場合の処理は考えなくても構いません.
なおファイルからの読み込みに便利な機能をこの課題のページの「技術要素」で紹介しています.
想定する実行方法
今回のプログラムでは折れ線グラフの「グラフデータファイル」を指定することになります. 指定の方法は次のいずれかとします.
- ファイル選択ダイアログを使う
- コマンドライン引数を使う
これら2つの方法のどちらにも対応するようにすることも考えられます.
以下,それぞれについて説明します.
ファイル選択ダイアログを使う
プログラム実行中に「ファイル選択ダイアログ」を開いて,グラフデータファイルを選択させることができます.
require 'gtr/fileselect' # プログラムの先頭にこの行を追加 : : class Turtle def draw ## ファイル選択ダイアログによるファイルの選択 # ファイルが選択された場合はその名前が得られる # キャンセルされた場合はnilが得られる fname = World.select_file
「ファイル選択ダイアログ」はポップアップウインドウでマウスでファイルを選択できるようにするものです. 「ファイル選択ダイアログ」の処理が終わるとファイル名が得られます. それを変数に代入してプログラムで利用できます. 上の例では「fname」に選択されたファイルの名前が代入されます.
なおファイルの選択をキャンセルすることもできます. キャンセルされた場合,ファイル名として「nil」が得られます(nil=何もない). 上の例では「fname」に「nil」が代入されます.
コマンドライン引数を使う
コマンドライン引数(ARGV)でグラフデータファイルを指定する場合, プログラムは次のように実行することになります. ここではプログラムのファイル名を「gtr_lineplot.rb」として, 折れ線グラフのグラフデータファイルの名前を「test_plot.txt」とします.
このときコマンドライン引数「test_plot.txt」は次のようにして取り込むことができます.
class Turtle def draw fname=retrieve() # 記憶させたファイル名を取り出す end end : : t = Turtle.new() # 亀を用意する t.push(*ARGV) # コマンドライン引数を亀に憶えさせる
亀を用意(Turtle.new)した直後に,コマンドライン引数を亀に憶えさせておいて(push), drawメソッドの中で折れ線グラフのグラフデータファイルの名前が必要になった時点で,それをretrieveによって取り出します(上の例ではfnameにファイル名が代入されます).retrieveを実行するたびにARGVの要素が一つずつ順に取り出されます.
pushの引数において,ARGVの前に「*」をつけることに注意して下さい(Rubyでは配列の前に「*」を付けてメソッドの引数に渡すと配列が要素に展開されてメソッドに渡されます).
[OPTION] プログラムとグラフデータファイルの拡張
次のようにプログラム,グラフデータファイルの仕様を拡張することが考えられます. これらの実現は必須ではありません.なおこれらの拡張を行った場合には提出するファイルの先頭の「=begin〜=end」の間にそのことを明記して下さい.
- 複数のグラフデータファイルへの対応
2つ以上のグラフデータファイルを読み込めるようにします. それぞれを別々の系列のデータとして複数の折れ線グラフを描きます. この場合,グラフデータファイルの指定にはコマンドライン引数(ARGV)を使った方が便利でしょう. - グラフデータファイルの仕様の拡張
1つのファイルに2つ以上のデータ系列が入れられるようにします. 具体的には,1つのファイルの中で,上で定義した書式のデータを「空行」を挟んで繰り返し並べたときに,それらを別々の系列のデータとして複数の折れ線グラフを描くようにします.
これらの拡張に同時に対応することも考えられます.
技術要素
プログラム作成に用いるであろう技術要素を以下に示します. すべてを使う必要はありません.
- 空白で区切られた数字列から整数の配列への変換
次のようにメソッドを定義することで, 空白で区切られた数字列(数字と空白で構成される文字列)を整数の配列に変換できます.# 空白区切りの数字列nstrを整数の配列に変換する def str2iary(nstr) nstr.split.map(&:to_i) end buff0 = '1 2 34 5' buff1 = ' 123 45 678 ' x0 = str2iary(buff0) # x0 == [1,2,34,5] x1 = str2iary(buff1) # x1 == [123,45,678]
数字列の間に空白が2つ以上並んでいても問題ありません.文字列の先頭と末尾の空白は無視されます.また末尾には改行があっても(なくても)結果は変わりません. なお引数が文字列でない場合には想定通りには処理されません. - 文字列末尾の「改行」の削除(chomp!)
getsメソッドで読み込んだ文字列の末尾には「改行」があります. chomp!メソッドで改行を取り除くことができます.File.open(fname) do |fin| line = fin.gets() line.chomp! # lineの末尾の改行を取り除く end
- 文字数のカウント(size)
sizeメソッドで文字列を構成する文字の個数を知ることができます. 日本語の文字も扱えます.s0 = 'hello!' n0 = s0.size # n0 == 6 s1 = 'こんにちは!' n1 = s1.size # n1 == 6
- if修飾子
if式においてif節の式が一つでelse節がない場合はifを後置できます. うまく利用すればプログラムの記述がシンプルになります.# if修飾子(x==1のときy=0とする) y = 0 if x == 1 # if修飾子を使わない記述(上と同等) if x == 1 y = 0 end # if修飾子は単独の式に対して適用されることに注意 x = y = 2 # x == 2, y == 2 x = 0; y = 0 if y < 1 # x == 0,y == 2となる(この場合「x = 0」は無条件に実行されていることに注意)
- ループの中断(break)
ループ(while,times,eachなど)の内部でbreakを実行すると, 繰り返し処理の途中でループを中断して先に進むことができます. 基本的に無条件でbreakする処理を記述することはありません. 通常はifなどの条件分岐の式と組み合わせて使います.ary = [1, 2, 0, 3, 4] ary.each do |x| break if x == 0 p x end p ary # 次のように表示される # 1 # 2 # [1, 2, 0, 3, 4]
- return
メソッドで「return 式」と記述すると,その時点で「式」の値をメソッドの値として,メソッドの実行を終了します.def f(x) return -x if x < 0 x+1 end y = f(-1) # y == 1 z = f(2.0) # z == 3.0
- ファイル読込終了の判定(eof?)
eof?メソッドでファイルを末尾まで読み終えているかどうかを判定できます.File.open(fname) do |fin| # すべての行を読み終えるまで繰り返す until fin.eof? line = fin.gets print line end end ## 上の例は次と同等 File.open(fname) do |fin| # すべての行を読み終えるまで繰り返す while line = fin.gets print line end end
- ブロックで定義される変数の有効範囲
ブロック(do…end,{…})内で定義された変数はブロック内部のみで有効です.hover { # x0,y0はここで定義したとする x0,y0 = pos() : : } # x0,y0はブロックの外では使えない moveto(x0,y0) # Error(undefined local variable or method)
プログラムテンプレート
次に示すプログラムのテンプレート(雛型)を使って下さい. このプログラムは名前を適宜変えた上で保存して利用してください.
サンプルファイル
この課題で指定している「グラフデータファイルの仕様」に従ったサンプルファイルを提供します.
サンプルプログラム
サンプルプログラムを示します. プログラムをブラウザの画面で開いたときに文字化けしてしまう場合には, ダウンロードしてEmacs等で開いてみて下さい.