プログラミング入門(2)

下記のページを参考にプログラミングの勉強を行います。
Rubyist Magazine - Ruby ではじめるプログラミング 【第 2 回】

式展開


「あなたの名前は○○○です。」の○○○の部分に変数を当てはめて表示するプログラム。

puts '名前を入力してください。'
name = gets
print 'あなたの名前は'
print name
puts 'です。'

f:id:ayaketan:20111208161644j:image

putsメソッドを使うと途中で改行されてしまうので、改行を行わないprintメソッドを使用した。
しかし、このプログラムを実行して名前にayaketanと入力したところ、ayaketanのところで改行されてしまった。
これはgetsメソッドで入力した文字列データの最後に改行コードが付いているから。
文字列の末尾の改行コードはchompメソッドで取り除くことができる。

puts '名前を入力してください。'
name = gets.chomp
print 'あなたの名前は'
print name
puts 'です。'

f:id:ayaketan:20111208161709j:image

式展開で文字列に変数を埋め込む


先ほどのプログラムは式展開という機能を使うと下記のように書くことができる。

puts '名前を入力してください。'
name = gets.chomp
puts "あなたの名前は#{ name }です。"

f:id:ayaketan:20111208161709j:image

#{}の中に変数を書いておくと、その変数の中身が文字列として埋め込まれる。
そして、式展開の機能を使うためには文字列を'(シングルコーテーション)ではなく"(ダブルコーテーション)で囲む必要がある。
また、#{}の中には変数以外にも四則演算屋メソッド呼び出しなど色々な物を書くことができる。

puts "1+1= #{ 1+1 }です。"
puts "10*10+5= #{ 10*10+5 }です。"

f:id:ayaketan:20111208161845j:image

a = 5
b = 2
puts "#{a}+#{b}= #{ a+b }です。"
puts "#{a}-#{b}= #{ a-b }です。"

f:id:ayaketan:20111208161927j:image
式展開では数値も自動的に文字列に変換されます。

やってみよう(その1)


式展開を使って作った文字列を変数に代入し、その変数を別の文字列の中で式展開してみよう。

str = "1+1=#{ 1+1 }"
puts "#{ str }は小学1年生で習います。"

f:id:ayaketan:20111208161947j:image

pメソッド


pメソッドを使うと様々なオブジェクトの中身を人間にわかりやすい形で表示することができる。
オブジェクトとは、数値や文字データのこと。

p 100
p 'abc'

f:id:ayaketan:20111208162027j:image

文字列データ(文字列オブジェクト)は"で囲まれて表示されます。
次のようにオブジェクトを変数に代入しても同様に中身を表示することができる。

a = 100
b = 'abc'
p a
p b

f:id:ayaketan:20111208162116j:image

getsメソッドの戻り値をpメソッドで表示してみる。

name = gets
p name

f:id:ayaketan:20111208162131j:image

入力した文字列が表示されているが、文字列の最後に\nという文字が付いている。
この\nが改行コード。改行コードを入力すると、コマンドプロンプト上では改行して表示される。
chompメソッドを使って末尾の改行コードを取り除くと次のようになる。

name = gets.chomp
p name

f:id:ayaketan:20111208162154j:image

\nがなくなっているのがわかる。

timesによるループ

5.times do |n|
 puts n
end

f:id:ayaketan:20111208162223j:image

5.times doの後ろに|n|という見慣れないコードがある。
このnは変数。変数nには0,1,2,3,4が順番にnに代入されながらループ処理が実行されていく。

エラー


いざプログラムを実行してみると、思わぬエラーが発生してプログラムが動かないことがある。
エラーは単純な入力ミスや誤った文法でプログラムを書けばすぐに発生する。
エラーが発生すると、その原因を調べるための手がかりがエラーメッセージとして表示される。

エラーになるプログラム


エラーが起こるように、正常なプログラムの1行目をコメントにした。

# a = 0
puts a

f:id:ayaketan:20111208162314j:image
このエラーメッセージはaという名前の変数やメソッドは存在しないことを知らせている。

次のプログラムでは、文字列データの「こんにちは」の最後に'がない。

puts 'こんにちは

f:id:ayaketan:20111208162345j:image
文字列が閉じられていないという旨のエラーメッセージが表示される。

次のプログラムはifに対応するendをコメントにして消してある。

a = 0
if a == 0
  puts 'a は 0 です。'
# end

f:id:ayaketan:20111208162402j:image
「syntax error」は文法が間違っているときに出るエラーメッセージ。

行番号に注目


それぞれのエラーメッセージの先頭を見るとtest.rb:数字:と表示されている。
test.rbはプログラムのソースファイル名で、その後ろの数字はエラーが発生している行番号を示す。
エラーには他にも種類があるが、ほとんどの場合は該当する行番号の部分に間違いがあるので、エラーが発生した場合はエラーメッセージを頼りにもう一度ソースファイルをよく確かめる。

配列


配列を作る


配列を使うと複数のオブジェクト(データ)をひとまとめにすることができる。
配列を作るにはいくつかの方法があるが、今回勉強するのは下記の形。

変数名 = [オブジェクト0, オブジェクト1, オブジェクト2, ……]

オブジェクト(データ)を,で区切ってデータ全体を[と]で囲む。
そして作られた配列に変数を使って名前を付ける。
次のプログラムはある3人の身長データを配列でまとめたもの。

values = [150, 174, 180]

このプログラムでは150と174と180という3つのデータをひとまとめにして、それにvaluesという名前を付けた。
valuesは変数名。
valuesの中身は3つの数字が順番に並んだ配列で、150という数値にアクセスするには次のようにする。

values[0]

pメソッドで配列の数字を表示してみる。

values = [150, 174, 180]
p values[0] # 150 を表示
p values[1] # 174 を表示
p values[2] # 180 を表示

f:id:ayaketan:20111208162444j:image

=を使って内容を変更することもできる。

values = [150, 174, 180]
values[0] = 155
p values[0] # 中身は 150 から 155 に変わっている
p values[1]
p values[2]

f:id:ayaketan:20111208162536j:image

配列内の最初のデータはvalues[1]ではなく、values[0]となっており、コンピュータは1からではなく、0から順番に数える。

添字(インデックス)


valuesの後ろに書いた[0]や[1]の数字部分を添字という。添字はインデックスと呼ばれることもある。
添字には数値を代入した変数を用いることができる。

values = [150, 174, 180]
index = 1       # 変数 index に1を代入
p values[index] # 174 が表示される

f:id:ayaketan:20111208162656j:image

前回勉強した「じゃんけんロボット」は、配列を使うと次のようになる。

puts 'じゃんけん'
sleep 1
values = ['グー', 'チョキ', 'パー']
r = rand(3) # r に 0 〜 2 の乱数を代入
puts values[r]

f:id:ayaketan:20111208162722j:image
if文もcase文もなくなり、プログラムが短くなった。

配列の中には数値だけでなく、文字列やその他のオブジェクトも入れることができる。

平均身長


次のプログラムは配列にセットされた身長から、平均身長を求めるプログラム。

values = [150, 174, 180]

n = values.size
puts "values には #{n} 人分のデータがあります。"

total = 0
n.times do |index|
  puts "身長が #{values[index]}cm の人がいます。"
  total += values[index]
end

puts "全員の身長の合計は #{total} cm です。"
puts "全員の身長の平均は #{total/n} cm です。"

f:id:ayaketan:20111208162756j:image

3行目の.sizeは配列の要素数を返すメソッド。ここでは変数nに3が代入される。
9行目の+=は加算を意味する記号で、ここでは変数totalにvalues[index]の値を加算しています。

配列もオブジェクト


配列の中にはどんなオブジェクトも入れることができる。
そして、配列もひとつのオブジェクトとして扱うことができる。
pメソッドで中身を表示してみる。

values = [0, 5, 'abc', 'あいう']
p values

f:id:ayaketan:20111208163003j:image

配列データの追加と削除


pushメソッドで配列の最後にオブジェクト(データ)を追加することができる。

values = []     # 空の配列を作成
p values        # values の中身を表示
values.push 0   # values に 0 を追加
p values
values.push 1   # values に 1 を追加
p values

f:id:ayaketan:20111208163038j:image

popメソッドで配列の最後のオブジェクト(データ)を取り出すことができる。

values = ['a', 'b']
p values
values.pop   # values から 'b' を削除
p values
values.pop   # values から 'a' を削除
p values

f:id:ayaketan:20111208163126j:image

配列の中に配列(多次元配列)


配列にはどんなオブジェクトでも入れることができる。
そして、配列もひとつのオブジェクトなので、配列に配列を入れることもできる。
次のプログラムを実行してみる。tblはただの変数名。

tbl = [[0,1,2], [3,4,5], ['a','b','c']]
p tbl

f:id:ayaketan:20111208163151j:image

pメソッドは多次元配列の中身も表示してくれる。
多次元配列から要素を取り出すには下記のようにします。

tbl = [[0,1,2], [3,4,5], ['a','b','c']]
p tbl[0]
p tbl[1]
p tbl[2]
p tbl[0][0]
p tbl[0][1]
p tbl[0][2]
p tbl[2][0]
p tbl[2][1]

f:id:ayaketan:20111208163220j:image

同じ配列定義を次のように書くこともできる。

tbl = [
  [0,1,2],
  [3,4,5],
  ['a','b','c']
]
p tbl

要素の数が多い場合はこのように改行を入れた方が見やすくなる。

次のプログラムは2次元配列とtimesのループ機能を使って画面にある文字絵を表示する。

tbl = [
  [1,1,1,0,0],
  [1,0,0,1,0],
  [1,0,0,1,0],
  [1,1,1,0,0],
  [1,0,1,0,0],
  [1,0,0,1,0]
]

y_max = tbl.size
y_max.times do |y|
  x_max = tbl[y].size
  x_max.times do |x|
    if tbl[y][x] == 1
      print ""
    else
      print ""
    end
  end
  print "\n" #改行する
end

f:id:ayaketan:20111208163301j:image

やってみよう(その2)


このプログラムを3次元配列(3重ループ)に改造して複数の絵を表示するプログラムを作成してみよう。

tbl = [
  [ 
    [1,1,1,0,0],
    [1,0,0,1,0],
    [1,0,0,1,0],
    [1,1,1,0,0],
    [1,0,1,0,0],
    [1,0,0,1,0]
  ],
  [
    [1,1,1,1,0],
    [1,0,0,0,0],
    [1,1,1,0,0],
    [1,0,0,0,0],
    [1,0,0,0,0],
    [1,0,0,0,0]
  ]
]

n_max = tbl.size
n_max.times do |n|
y_max = tbl[n].size
  y_max.times do |y|
    x_max = tbl[n][y].size
    x_max.times do |x|
      if tbl[n][y][x] == 1
        print ""
      else
        print ""
      end
    end
    print "\n" #改行する
  end
    print "\n" #改行する
end

f:id:ayaketan:20111208163349j:image

配列を使ったゲームブック


前回作成したゲームブックプログラムを配列を使って作ってみる。

msg0 = "3本の分かれ道があります。どの道を進みますか。\n" +
       "  1 左の道\n  2 真ん中の道\n  3 右の道"
msg1 = "あっ!\n落とし穴に落ちてしまいました。\n〜 GAME " +
       "OVER 〜"
msg2 = "真ん中の道をまっすぐ歩いていくと……\n宝箱をみつ" +
       "けました!\n  1 そのままにしておく\n  2 あける"
msg3 = "しばらく歩き続けると もとの場所にもどってしまい" +
       "ました。\n  1 次へ"
msg4 = "宝箱には見向きもせず お家に帰りました。\n〜 GAM" +
       "E OVER 〜"
msg5 = "パカッ\nまばゆい光があふれだす……\n100枚の金" +
       "貨を手に入れました!"

tbl = [
  [msg0,   1,   2,   3],
  [msg1, nil, nil, nil],
  [msg2,   4,   5, nil],
  [msg3,   0, nil, nil],
  [msg4, nil, nil, nil],
  [msg5, nil, nil, nil],
]

scene = 0
while true
  scene_data = tbl[scene]
  message = scene_data[0]
  puts message

  if scene_data[1] == nil
    exit
  end

  print '  数字を入力してください '
  input_value = gets.to_i

  if input_value > 0
    next_scene = scene_data[input_value]
    if next_scene == nil
      puts '不正な値が入力されました'
    else
      scene = next_scene
    end
  else
    puts '不正な値が入力されました'
  end

  sleep 0.5
  print "\n"
end

f:id:ayaketan:20111208163420j:image