Rubyチュートリアル

takashi42332007-05-12


9章のHashクラスから,
Hashの概念はPerlで知ってるから新情報は特にない感じ.
配列は[]で,ハッシュは{}っていうのは何か忘れそう...


インスタンス変数はオブジェクトが生き残っている限り生き残る
変数名の最初に@をつければそれがインスタンス変数なるんだって.


また,オブジェクトを生成したときの初期化.すなわちjavaでいうコンストラクタをrubyではinitializeというメソッドで表現する.あと,個人的に面白かったのが,メソッドがbloom型を返すときは,末尾に?をつけるメソッドを定義するという慣習.

def hungry?
    #  メソッドの名前は"?"で終わることができます。
    #  通常、メソッドがtrueかfalseのどちらかを返すときだけ、
    #  この名前を使います。このように:
    @stuffInBelly <= 2
  end

これは結構使うと便利というか,少しオシャレな気がする.


以下私的解答

OrangeTreeクラスを作ってみなさい。このクラスには、木の高さを返すheightメソッドと、メソッドを呼ぶことで、1年分時間を進めるoneYearPassesメソッドがあります。毎年、この木は成長し大きくなります(オレンジの木が1年に伸びる分だけ)。そして、ある年限が来たら(これもメソッド呼び出しによります) その木は死んでしまいます。最初の2,3年は実をつけませんが、その後は実がなる様にします。で、成長した木は若い木よりたくさん実をつけます。このあたりはあなたが納得するよう調節してみましょう。そして、もちろんcountTheOrages(木になっているオレンジの数を返す)メソッドと、 pichAnOrange(オレンジをひとつ摘むメソッド。このメソッドで @orangeCountが、1だけ小さくなり、いかにおいしいオレンジだったかを告げる文字列かあるいは、もう木にオレンジがなっていないことを告げる文字列かを返します。)を実行できるようにしなければいけません。それと、ある年に取り残したオレンジは次の年には落ちてしまうようにしましょう。

class Orangetree

  #初期化
  def initialize
    @treeHeight = 0.3
    @treeYears = 0
    @orangeCount = 0
  end

  #高さを返す
  def height
    puts @treeHeight
  end

  #1年経過させる.
  def oneYearPasses
    @treeYears += 1
    if liveOrDead?
      p "An orange tree is die..."
      exit #プログラム終了
    end
    #木の高さは1年に0.7伸びると勝手に設定
    @treeHeight += 0.7
    #オレンジの実の数は年齢-1を上限とする乱数で決める
    @orangeCount = rand(@treeYears - 1)
  end

  #木になっているオレンジの数を出す
  def countTheOranges
    p @orangeCount.to_i
  end

  #オレンジを一個とる
  def pichAnOrange
    if exitsOrange?
      @orangeCount -= 1
      p "Orange is delicious!"
    else
      p "Orange is not here!"
    end
  end


  private #ここからprivate

  #木がまだ生きているかどうかの判定
  def liveOrDead?
    @treeYears > 10
  end

  #オレンジが存在するかどうかの判定
  def exitsOrange?
    @orangeCount >= 1
  end
end


tree = Orangetree.new
tree.oneYearPasses
tree.oneYearPasses
tree.oneYearPasses
tree.oneYearPasses
tree.oneYearPasses
tree.oneYearPasses
tree.oneYearPasses
tree.countTheOranges
tree.pichAnOrange
tree.countTheOranges

赤ちゃんドラゴンと会話が出来るようなプログラムを書いてみましょう。 feedやwalkのようなコマンドを入力できるようにしてドラゴンに対してそれらのメソッドが呼ばれるようにします。もちろん、入力されたものは文字列なので、ある種のメソッドに転送する処理 をしなくてはならないでしょう。つまり、何の文字が入力されたかをチェックして適切なメソッドを呼び出すという処理です。

class Dragon

  def talk 
    puts "Input your word >>"
    word = gets.chomp
    case word
      when "feed"
      feed
      when "walk"
      walk
      when "putToBed"
      putToBed
      when  "toss"
      toss
      when "rock"
      rock
    end
  end


  def initialize name
    @name = name
    @asleep = false
    @stuffInBelly     = 10  #  最初彼はおなかいっぱいです。
    @stuffInIntestine =  0  #  トイレはまだ大丈夫。(Bellyは胃、Intestineは腸です。)

    puts @name + ' は生まれました.'
  end

  def feed
    puts 'あなたは ' + @name + 'に食べ物を与えます.'
    @stuffInBelly = 10
    passageOfTime
  end

  def walk
    puts 'あなたは ' + @name + 'をトイレに連れて行きます.'
    @stuffInIntestine = 0
    passageOfTime
  end

  def putToBed
    puts 'あなたは ' + @name + ' を寝かしつけます.'
    @asleep = true
    3.times do
      if @asleep
        passageOfTime
      end
      if @asleep
        puts @name + ' はいびきをかいて, 部屋中煙だらけ.'
      end
    end
    if @asleep
      @asleep = false
      puts @name + ' はゆっくり目を覚ます.'
    end
  end

  def toss
    puts 'あなたは ' + @name + ' を空中に投げ上げます.'
    puts '彼はキャハキャハ笑い, あなたの眉毛は焼け焦げた.'
    passageOfTime
  end

  def rock
    puts 'あなたは ' + @name + ' を優しく揺すります.'
    @asleep = true
    puts '彼は短くうとうと...'
    passageOfTime
    if @asleep
      @asleep = false
      puts '...でもやめるとすぐ起きちゃう.'
    end
  end

  private

  #  "private"というのは、ここで定義されているメソッドが
  #  オブジェクト内部のものであるという意味です。
  #  (あなたはドラゴンにえさを与えることはできますが、
  #  おなかがすいているかどうかを訊くことはできません。)

  def hungry?
    #  メソッドの名前は"?"で終わることができます。
    #  通常、メソッドがtrueかfalseのどちらかを返すときだけ、
    #  この名前を使います。このように:
    @stuffInBelly <= 2
  end

  def poopy?
    #うんちが出そう?
    @stuffInIntestine >= 8
  end

  def passageOfTime
    if @stuffInBelly > 0
      #  食べたものは、胃から腸へ移動
      @stuffInBelly     = @stuffInBelly     - 1
      @stuffInIntestine = @stuffInIntestine + 1
    else  #  私たちのドラゴンは飢えました!
      if @asleep
        @asleep = false
        puts '彼は突然跳び起きます!'
      end
      puts @name + ' は飢え死にしそう!  死に物狂いの彼は"あなた"を食べてしまいました!'
      exit  #  プログラムを終了します。
    end

    if @stuffInIntestine >= 10
      @stuffInIntestine = 0
      puts 'おっと!  ' + @name + ' はやっちゃったようです...'
    end

    if hungry?
      if @asleep
        @asleep = false
        puts '彼は突然起きます!'
      end
      puts @name + 'のおなかはゴロゴロ言ってます...'
    end

    if poopy?
      if @asleep
        @asleep = false
        puts '彼は突然起きます!'
      end
      puts @name + ' はうんちをしたくて踊っています...'
    end
  end

end

pet = Dragon.new 'Norbert'

pet.talk
pet.talk
pet.talk
pet.talk
pet.talk
pet.talk
pet.talk
pet.talk

問2は思った以上に簡単だったんだけど,こんなんで本当にええんかな?
と思ってみたり.

10章に入ってブロックについての説明.
意味は分かるんだけど,いつ使うのかとかがいまいちしっくりこない感じ

おじいさんの時計 。 ブロックを取って、今日過ぎた時間の回数だけ、ブロックを呼ぶメソッドを書きなさい。それで、もし、ブロックとして do puts 'DONG!' endを渡したとしたら、それはおじいさんの時計のような (そんなたぐいの)チャイムを打つことになります。できたメソッドを、 (先ほどの例を含めて)2,3の違うブロックを使ってテストしてみなさい。
ヒント:いまの時間を得るには Time.now.hour が使えます。でも、この時間というのは、0から 23の数字を返しますので、それを普通の時計の前面にある数字 (1から 12)へと変換しなければなりません。

# #鐘をならすブロック
dong = Proc.new do
  p "DONG!!"
end


#今回メインとなるメソッド
#現在の時刻を計算する
def oldClock someProc
  #現在時刻を獲得
  time = Time.now.hour

  #時刻を12時間系に変換
  if time >= 12
    time -= 12
  end

  #現在の時刻分dongブロックをコールする
  time.times do
    someProc.call 
  end 
end

oldClock dong

続きを作成中だけど,何かここにきていまいち何が便利なのかがわからないから,
その辺は勉強する必要があると思う.