課題
この課題では,正多角形を描画するメソッドpolygonを次のように定義してください.
# 正多角形を描く
# n: 頂点数
# s: 1辺の長さ
# mode: 描画モード(:left,:right,:center)
def polygon(n,s,mode)
end
- n → 頂点の個数を指定する
- s → 1辺の長さを指定する
- mode → 正多角形の描き方を次のいずれかで指定する(ここで指定しているデータの詳細については以下を参照のこと)
:left 現在位置から左回りで描く.描画開始時に亀が向いている方向に最初の辺を描く. :right 現在位置から右回りで描く.描画開始時に亀が向いている方向に最初の辺を描く. :center 現在位置が中心になるように描く.描画開始時に亀が向いている方向に頂点が配置されるようにする. - n,s,modeはそれぞれ適切に指定されると仮定してよい
- [!] メソッド内部において,正多角形を描画した後,亀が描画開始時と同じ位置,同じ向きに戻るようにする
注意
- プログラムに記述する式はできるだけ簡単にするよう心がけて下さい.
メソッドの利用例
メソッドの利用例を示します(s0,s1,s2は定義済みとします).
# 1辺s0の正五角形を描く(現在位置から左回り) polygon(5,s0,:left) # 1辺s1の正八角形を描く(現在位置から右回り) polygon(8,s1,:right) # 1辺s2の正六角形を描く(現在位置を中心として亀が向いている方向に頂点を配置) polygon(6,s2,:center)
それぞれの場合に描く正多角形を次に示します(辺の長さは適当に決めています).赤い矢印が描画開始時の亀の位置と向きを表しています.すでに述べた通り,描画終了時には亀が描画前と同じ状態(位置,向き)に戻っていることを想定しています.

modeに指定するデータについて
引数modeに利用しているのは「Symbol」(シンボル)という種類のデータです.
Symbolは上のように「:」につづけて「名前」を記述して表現します(名前の前に「:」を付けるとSymbolになります.「:」は名前には含まれません). 今回の課題のためにはSymbolの詳細を理解する必要はありません. Symbolについて同一性が判定できることを知っていれば十分でしょう.
s = :hello # sは「hello」という名前のSymbol t = :bye # tは「bye」という名前のSymbol if s == :world # ==> false (:hello ≠ :world) x = 0 elsif s == t # ==> false (:hello ≠ :bye) x = 1 else x = 2 end # ==> x == 2
なお文字列とSymbolは異なる種類のデータです. ただし相互に変換は可能です.
a = :hello b = 'hello' a == b # ==> false (Symbolと文字列は等しくない) b1 = b.to_sym # bをSymbolに変換(b1==:hello) a == b1 # ==> true a1 = a.to_s # aを文字列に変換(a1=='hello') a1 == b # ==> true
プログラムテンプレート
次に示すプログラムのテンプレート(雛型)を使って下さい. このプログラムは名前を適宜変えた上で保存して利用してください.
Tips
- データ入力
-
次のように記述することで,nとsを空白区切りで指定して,整数として得ることができます.
n,s = ask('nとsを空白で区切って指定してください').split.map(&:to_i)
askでキーボードから文字列を受け取って,空白で区切ってから(split),それぞれを整数に変換しています(map(&:to_i)) nとsに設定する整数は,例えば次のように指定します.8 90
この例の場合,n=8,s=90と代入されることになります.
modeを指定するには次のように記述します.mode = ask('mode(left/right/center)を指定してください').to_sym
askでキーボードから文字列を受け取って,to_symによって文字列をSymbol(シンボル)に変換しています. modeに設定するSymbol(シンボル)は,次の例のように単純に文字列(left/right/center)で指定します.left
この例の場合はmode=:leftと代入されます.
[参考] 度(degree)を引数とする三角関数
亀のメソッド定義において,度(degree)を引数とする三角関数(sin,cos,tan)が利用できます.
class Turtle def draw theta = 45 # 45度 r = 100 dx = r*cos(theta) # Math.cos(theta)ではない dy = r*sin(theta) # Math.sin(theta)ではない move(dx,dy) # キャンバスのx軸正の方向から左回りで45度の方向へr進む end end
Math.cos(x),Math.sin(x),Math.tan(x)の引数は弧度(radian)ですので注意して下さい.
class Turtle
def draw
# 「OK」というメッセージを表示する
if Math.sin(Math::PI/2) == sin(90)
say('OK')
end
end
end
[参考] Symbol
ここではRubyの「Symbol」(シンボル)について簡単に説明します. 課題のためには以下を理解する必要はありません.
Symbolは「文字列」(文字が並んだデータ)と似ていますが,異なる種類のものです. Symbolとは「名前」で区別されるデータです. コロン(:)のあとに「名前」を書いて定義します. なお「:」は名前には含まれません.それにつづく部分が名前です.
:a_symbol # シンボル
上で述べたようにSymbolは文字列(文字の並び)ではありません. 文字列のデータは書き換えられます.一方でSymbolは書き換えられません. 同じ文字の並びで構成される文字列(の実体)はいくつでも作れますが,同一の名前のSymbol(の実体)は一つしかありません.
# # 文字列とそのデータの実体について調べてみる # s = "ace" # 文字列 t = "ace" # 文字列 s == t # ==> true (s,tの値は等しいか?→等しい) s.equal?(t) # ==> false (s,tは同一の実体か?→そうではない.「equal?」はデータの実体の同一性を判定する) # sの1文字目を"A"に書き換える. s[0,1] = "A" # s == "Ace" # sへの変更はtには影響しない.つまりs,tの実体は同じではない.たまたま同じ文字が並んでいただけ. s == "Ace" # ==> true (sの値は"Ace"に等しいか→等しい) t == "ace" # ==> true (tの値は"ace"に等しいか→等しい) s == t # ==> false (s,tの値は等しいか?→等しくない) s.equal?(t) # ==> false (s,tは同一の実体か?→そうではない) # # Symbolとそのデータの実体について調べてみる # x = :ace # Symbol y = :ace # Symbol z = :Ace # Symbol x == y # ==> true (x,yの値は等しいか?→等しい.名前(ace)が同一である) x == z # ==> false (x,zの値は等しいか?→等しくない.名前(ace,Ace)が異なる) x.equal?(y) # ==> true (x,yの実体は同一である) x.equal?(z) # ==> false (x,zの実体は異なる) # # 文字列とそのデータの実体について調べてみる(2) # t = s # tをsと同じ文字列データと対応させる t.equal?(s) # ==> true (s,tは同一の実体である) t[2,1] = "t" # tの3番目の文字を"t"に書き換える(t=="Act") s == "Act" # ==> true (sの値は"Act"に等しいか→等しい)