プログラミング入門(2)
下記のページを参考にプログラミングの勉強を行います。
Rubyist Magazine - Ruby ではじめるプログラミング 【第 2 回】
式展開
「あなたの名前は○○○です。」の○○○の部分に変数を当てはめて表示するプログラム。
puts '名前を入力してください。' name = gets print 'あなたの名前は' print name puts 'です。'
putsメソッドを使うと途中で改行されてしまうので、改行を行わないprintメソッドを使用した。
しかし、このプログラムを実行して名前にayaketanと入力したところ、ayaketanのところで改行されてしまった。
これはgetsメソッドで入力した文字列データの最後に改行コードが付いているから。
文字列の末尾の改行コードはchompメソッドで取り除くことができる。
puts '名前を入力してください。' name = gets.chomp print 'あなたの名前は' print name puts 'です。'
式展開で文字列に変数を埋め込む
先ほどのプログラムは式展開という機能を使うと下記のように書くことができる。
puts '名前を入力してください。' name = gets.chomp puts "あなたの名前は#{ name }です。"
#{}の中に変数を書いておくと、その変数の中身が文字列として埋め込まれる。
そして、式展開の機能を使うためには文字列を'(シングルコーテーション)ではなく"(ダブルコーテーション)で囲む必要がある。
また、#{}の中には変数以外にも四則演算屋メソッド呼び出しなど色々な物を書くことができる。
puts "1+1= #{ 1+1 }です。" puts "10*10+5= #{ 10*10+5 }です。"
a = 5 b = 2 puts "#{a}+#{b}= #{ a+b }です。" puts "#{a}-#{b}= #{ a-b }です。"
やってみよう(その1)
式展開を使って作った文字列を変数に代入し、その変数を別の文字列の中で式展開してみよう。
str = "1+1=#{ 1+1 }" puts "#{ str }は小学1年生で習います。"
pメソッド
pメソッドを使うと様々なオブジェクトの中身を人間にわかりやすい形で表示することができる。
オブジェクトとは、数値や文字データのこと。
p 100 p 'abc'
文字列データ(文字列オブジェクト)は"で囲まれて表示されます。
次のようにオブジェクトを変数に代入しても同様に中身を表示することができる。
a = 100 b = 'abc' p a p b
getsメソッドの戻り値をpメソッドで表示してみる。
name = gets p name
入力した文字列が表示されているが、文字列の最後に\nという文字が付いている。
この\nが改行コード。改行コードを入力すると、コマンドプロンプト上では改行して表示される。
chompメソッドを使って末尾の改行コードを取り除くと次のようになる。
name = gets.chomp p name
\nがなくなっているのがわかる。
timesによるループ
5.times do |n| puts n end
5.times doの後ろに|n|という見慣れないコードがある。
このnは変数。変数nには0,1,2,3,4が順番にnに代入されながらループ処理が実行されていく。
エラー
いざプログラムを実行してみると、思わぬエラーが発生してプログラムが動かないことがある。
エラーは単純な入力ミスや誤った文法でプログラムを書けばすぐに発生する。
エラーが発生すると、その原因を調べるための手がかりがエラーメッセージとして表示される。
エラーになるプログラム
エラーが起こるように、正常なプログラムの1行目をコメントにした。
# a = 0
puts a
このエラーメッセージはaという名前の変数やメソッドは存在しないことを知らせている。
次のプログラムでは、文字列データの「こんにちは」の最後に'がない。
puts 'こんにちは
文字列が閉じられていないという旨のエラーメッセージが表示される。
次のプログラムはifに対応するendをコメントにして消してある。
a = 0 if a == 0 puts 'a は 0 です。' # end
「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 を表示
=を使って内容を変更することもできる。
values = [150, 174, 180] values[0] = 155 p values[0] # 中身は 150 から 155 に変わっている p values[1] p values[2]
配列内の最初のデータはvalues[1]ではなく、values[0]となっており、コンピュータは1からではなく、0から順番に数える。
添字(インデックス)
valuesの後ろに書いた[0]や[1]の数字部分を添字という。添字はインデックスと呼ばれることもある。
添字には数値を代入した変数を用いることができる。
values = [150, 174, 180] index = 1 # 変数 index に1を代入 p values[index] # 174 が表示される
前回勉強した「じゃんけんロボット」は、配列を使うと次のようになる。
puts 'じゃんけん' sleep 1 values = ['グー', 'チョキ', 'パー'] r = rand(3) # r に 0 〜 2 の乱数を代入 puts values[r]
配列の中には数値だけでなく、文字列やその他のオブジェクトも入れることができる。
平均身長
次のプログラムは配列にセットされた身長から、平均身長を求めるプログラム。
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 です。"
3行目の.sizeは配列の要素数を返すメソッド。ここでは変数nに3が代入される。
9行目の+=は加算を意味する記号で、ここでは変数totalにvalues[index]の値を加算しています。
配列もオブジェクト
配列の中にはどんなオブジェクトも入れることができる。
そして、配列もひとつのオブジェクトとして扱うことができる。
pメソッドで中身を表示してみる。
values = [0, 5, 'abc', 'あいう'] p values
配列データの追加と削除
pushメソッドで配列の最後にオブジェクト(データ)を追加することができる。
values = [] # 空の配列を作成 p values # values の中身を表示 values.push 0 # values に 0 を追加 p values values.push 1 # values に 1 を追加 p values
popメソッドで配列の最後のオブジェクト(データ)を取り出すことができる。
values = ['a', 'b'] p values values.pop # values から 'b' を削除 p values values.pop # values から 'a' を削除 p values
配列の中に配列(多次元配列)
配列にはどんなオブジェクトでも入れることができる。
そして、配列もひとつのオブジェクトなので、配列に配列を入れることもできる。
次のプログラムを実行してみる。tblはただの変数名。
tbl = [[0,1,2], [3,4,5], ['a','b','c']] p tbl
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]
同じ配列定義を次のように書くこともできる。
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
やってみよう(その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
配列を使ったゲームブック
前回作成したゲームブックプログラムを配列を使って作ってみる。
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