[ プログラミング演習(Ruby) >  プログラミング演習(Ruby) 課題(2024) >  [課題11] 正多角形を描画するメソッド ]

[課題11] 正多角形を描画するメソッド

課題

タートルグラフィクスで 以下に示す要領で,正多角形を描画するメソッドを定義した上で, そのメソッドを利用して,正多角形で構成される適当な図形を描くプログラムを作成して, プログラムを提出してください.

この課題では,正多角形を描画するメソッドpolygonを次のように定義してください.

  # 正多角形を描く
  # n: 頂点数
 # s: 1辺の長さ
  # mode: 描画モード(:left,:right,:center)
  def polygon(n,s,mode)


  end

注意

メソッドの利用例

メソッドの利用例を示します(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"に等しいか→等しい)

[ プログラミング演習(Ruby) >  プログラミング演習(Ruby) 課題(2024) >  [課題11] 正多角形を描画するメソッド ]