(5)10/26の授業内容

  1. メソッドのまとめ
  2. メソッドを定義するにはdef-endが用いられます。

    def メソッド名(引数リスト)
      定義本体
    end

    def-endの中に記載される定義本体のうち、原則として最終行が返り値となります。このため、下記のshohizeiメソッドでは、計算された数字が返り値となり、taxメソッドでは、「税込み価格は○円です」という画面表示が返り値となります。返り値がどのようなものであるかにより、メソッドを呼び出す方法も変化します。

    def shohizei(a)
      a * 1.05
    end
    ----------
    def tax(x)
      price = x * 1.05
      printf ("税込み価格は%d円です\n",price)
    end

    taxメソッドを呼び出す場合には、単にtax(x)と何らかの引数を与えて呼び出せばよいですが、shohizeiメソッドの場合引数を与えて呼び出しても数字を返してくれるだけですから、結果が画面に表示されません。返り値がどのようなものになるのかを踏まえた上で、呼び出し方法を考える必要があります。

    def shohizei(a)
      a * 1.05
    end
    
    printf ("税込み価格は%d円です\n",shohizei(1000)) #有効
    shohizei(1000) #無効
    
    a=shohizei(1000)
    printf ("税込み価格は%d円です\n",a) #有効
    
    ----------
    def tax(x)
      price = x * 1.05
      printf ("税込み価格は%d円です\n",price)
    end
    
    printf ("税込み価格は%d円です\n",shohizei(1000)) #無効
    shohizei(1000) #有効

    メソッドに渡す引数の数(前回のレポートから)

    上記では、引数が1つ必要なメソッドを例に挙げていますが、引数が0のメソッドや、2つ以上必要とするメソッドも定義可能です。

    #!/usr/koeki/bin/ruby
    #引数が0の場合(単にこんにちはと表示するだけのメソッド:hello)
    
    def hello()
      print "こんにちは!\n"
    end
    
    hello

    引数が不要な場合は、引数リストのカッコ内は空にします。以下の引数を2つ以上使うメソッドの例については、前回の課題からよくできていたものをいくつか紹介します。

    #!/usr/koeki/bin/ruby
    #喫煙指数を調べるメソッド
    print "あなたの喫煙指数を調べます。数値を入力してください。 \n"
    
    def sisuu(ryou, jikan)
      if ryou < 0 || jikan < 0
        return nil
      end
      return ryou*jikan
    end
    
    STDERR.print "あなたは一日に平均何本たばこを吸いますか?\n"
    ryou = gets.to_i
    
    STDERR.print "あなたは何年間たばこを吸っていますか?\n"
    jikan = gets.to_i
    
    printf("あなたの喫煙指数は%dです。400以上から肺ガンに注意が必要です。\n", sisuu(ryou, jikan))
    #!/usr/koeki/bin/ruby
    #残りの人生を計算するメソッド
    def inoti(x,y)
      a=x-y
      a=a*365
      printf ("あなたの残りの人生は、%d日です。\n",a)
    end
    
    STDERR.print ("何歳まで生きたいですか?\n")
    b = gets.chomp!.to_i
    STDERR.print ("今何歳ですか?\n")
    c = gets.chomp!.to_i
    inoti(b,c)
    #!/usr/koeki/bin/ruby
    #とにかく長いメソッド
    def zeikomi(a,b)
      last = a - b
      STDERR.print "時間帯(1:日中、2:午後8時以降)"
      zikan = STDIN.gets.chomp!
      if zikan == "1"
        wari = last
      elsif zikan == "2"
        wari = last - last * 0.2
      printf ("タイムサービスにつき、2割り引きで%d円になります。\n",wari)
      end
      zei = wari * 1.05
      printf ("お会計は%d円、税込み%dになります。\n",wari,zei)
      STDERR.print "いくらでお支払しますか?:"
      money = gets.chomp!.to_i
      printf ("%d円お預かりします。%d円のお返しです。\n",money,money-zei)
      print ("ありがとうございました。またのご来店をお待ちしております。\n")
    end
    
    syoukei = []
    i = 0
    sum = 0
    goukei = 0
    henpin = []
    j = 0
    
    while true
      STDERR.print "いくらの商品を買いますか?(0で、お買い物終わり)"
      syoukei[i] = gets.chomp!.to_i
      if syoukei[i] == 0
        then break
      end
      sum += syoukei[i]
      i += 1
    end
    
    while true
      STDERR.print "いくらの商品を返品しますか?(0で返品終了)"
      henpin[j] = gets.chomp!.to_i
      if henpin[j] == 0
        then break
      end
      goukei += henpin[j]
      j += 1
    end
    
    zeikomi(sum,goukei)
    #!/usr/koeki/bin/ruby
    #2つのメソッドを定義しているケース
    def syoku(a,b,c,d)
      sum = a + b + c + d
    end  
    def pay(a,b,c,d,e)
      sum = a*200 + b*350 + c*350 + d*450 + e*200
    end
    
    mon = 0
    sova = 0
    ra = 0
    ca = 0
    tei = 0
    ice = 0
    
    print "** カフェテリア利用状況シミュレータ ***\n"
    print "\n"
    
      STDERR.print "利用した月を入れて下さい。>"
      mon = gets.chomp!.to_i
      STDERR.print "そば/うどんを何杯食べましたか? >"
      sova = gets.chomp!.to_i
      STDERR.print "ラーメンを何杯食べましたか? >"
      ra = gets.chomp!.to_i
      STDERR.print "カレーを何杯食べましたか? >"
      ca = gets.chomp!.to_i
      STDERR.print "夕定食を何食食べましたか? >"
      tei = gets.chomp!.to_i
      STDERR.print "ソフトクリームを何個食べましたか? >"
      ice = gets.chomp!.to_i
    
    print "\n"
    printf ("***** %d月のカフェテリア利用状況 *****\n",mon)
    printf ("合計は %d食 利用していました。\n",syoku(sova, ra, ca, tei))
    printf ("合計で%d円分(税込) 食べました。\n",pay(sova, ra, ca, tei, ice))
    print "\n"
    print "*** 注意 ***\n"
    print "※ 大盛り、トッピング、ご飯やおかずには対応していません。\n"
    print "※ ソフトクリームは1食には含めません。認めません。\n"

    数が多かったメソッドは下記の通り。

    メソッドの返り値は最後の行の結果とは限らない

    if-endを使った場合には最後の行の結果が返り値とはならないことがあります。

    #!/usr/koeki/bin/ruby
    
    def min(x,y)
      if x < y
        (return) x  #returnは省略可能
      else
        (return) y  #returnは省略可能
      end
    end
    

    def-end部分のみですが、これは2つの引数を比較して小さい方を返り値とするというメソッド(min)です。最後の行ではなく、途中で値を返す場合にはreturnを使いますが省略可能です。

    引数にはデフォルト値を指定することができる

    引数が必要なメソッドにおいて、引数が省略された場合に適用される値(デフォルト値)を指定しておくことができます

    #!/usr/koeki/bin/ruby
    
    def sankaku(x,y=10)
      x * y / 2
    end
    
    printf ("面積は%4.2f平方センチメートルです\n", sankaku(5))  #=>5*10/2=25
    printf ("面積は%4.2f平方センチメートルです\n", sankaku(5,8))  #=>5*8/2=20

    上記の例ではyのデフォルト値として10が与えられている。sankaku(5)で呼び出した場合は、xの値しか指定していないのでyには自動的に10が代入される。sankaku(5,8)で呼び出した場合はx、yいずれも値が指定されているのでデフォルト値は代入されない。

    なお、定義したメソッドを呼ぶときは引数を順番に与えていくため、前の引数を省略して後ろの引数を指定することはできません。具体的に言うと、上記の例でsankaku(5)となっている場合、5は自動的にxに与えられます。このため、xにデフォルト値を与え、yには与えていない場合はエラーになってしまいます。したがって、

    ○ def sankaku(x=10, y=8) 
    ○ def sankaku(x, y=8) 
    × def sankaku(x=10, y) 

    となります。

    メソッドに配列を渡すこともできる

    2回目の授業のbokin.rbを改良してみましょう。募金の合計額を算出するtotalというメソッドを定義します。

    #!/usr/koeki/bin/ruby
    
    def total(yen)  #yenは数値の入っている配列
      sum = 0
      x = 0
      while x < yen.length-1  #.lengthで配列の中のデータの個数を調べる
        sum += yen[x]
        x += 1
      end
      sum  #最終行が返り値となるので単にsumと書いている
    end
    
    bokin = []
    i = 0
    
    while true
      STDERR.print "募金お願いします"
      bokin[i] = gets.chomp!.to_i
    
      if bokin[i] == 0
        then break
      end
    
      i += 1
    end
    
    printf ("募金の合計は%d円でした\n",total(bokin))

  3. プログラムを楽しくするテクニック
  4. 乱数を発生する

    #!/usr/koeki/bin/ruby
    
    janken = ["グー","チョキ","パー"]
    
    srand
    comp=rand(3)
    
    STDERR.print "じゃんけんぽん!(0: ぐー,1: ちょき,2: ぱー) :"
    user = gets.chomp!.to_i
    
    printf "あなたは %s でした \n", janken[comp]
    printf "わたしは %s でした。\n", janken[user]

    少し間を空ける

    #!/usr/koeki/bin/ruby
    
    srand
    rocket = rand(2)
    
    print "打ち上げ10秒前\n"
    sleep(1)
    
    9.downto(1) do |i|
      printf ("%s秒前\n",i)
      sleep(1)
    end
    
    if rocket == 1
      print "発射成功!!\n"
    else
      print "ドカーン!!\n"
    end

    時刻を取得する

    #! /usr/koeki/bin/ruby
    
    STDERR.print "問題を出します。制限時間は5杪です。準備は良いですか(y or n)"
    junbi = gets.chomp!
    
    if junbi == "y"
      sleep(1)
      print "では出題します\n"
    else
      print "準備が出来たらもう一度実行して下さい\n"
      exit(1)
    end
    
    sleep(1)
    print "\n"
    print "イギリスの正式名称を英語で答えなさい\n"
    
    start = Time.now.to_i
    
    while true
    if Time.now.to_i - start > 5
      print "\a"
      print "はい時間切れ\n"
      break
    end
    end

本日の課題

def-endと今回新たに学んだrand、sleep、Time.nowを組み合わせて何かプログラムを作成する(どれか1つ使えばよい。もちろん複数利用も可)。面白いもの、役に立つもの、誰も思いつかないようなものを作ってみよう。


作成したプログラムや実行結果をメールでnaoya@e.koeki-u.ac.jp宛に送る

課題の提出期限は11月1日(火)23:59までです


メール送信時の注意

説明のポイント:何をするプログラムなのか(プログラムの概要)、どんなメソッドを定義したのか(def-endの中味)、randや、sleep、Time.nowをどのように活用したかの3点を中心に見ます

レポート採点基準:期限内提出(2点)、プログラムの正誤・複雑さ(3点)、説明(2点)、オリジナリティ(2点)、指示通りにメールを送っているか(1点)

オリジナリティの評価基準は、他の先生のページに記載された サンプルプログラムを真似する(0点)、同じメソッドを作った人が10人の場合 (1点)、同じプログラムを作った人が5人の場合(1.5点)、誰も思いつかないようなプログラム(2点)を基準とします

Tips

emacsについて

Mewについて