タイピングテスト・チームワーク


タイピングテスト

念のため、テスト終了後に自分の最高得点をs4で提出する。(得点は ☆ Score の欄で確認すること)。


データの取り扱い

プログラムを設計する際には、コード(処理)と処理の対象になるデータを分離すべきである。

例えば、クイズプログラムの場合で考えよう。以下のように、質問の内容や正解に関する情報をソースコードに埋め込むスタイルは効率が良くない。なぜなら、各質問に対して同じ処理を繰り返している。そして、もし将来に例えばユーザーの解答が間違っている場合に正解を表示するという変更を導入したいなら、すべての質問の処理を変えなければいけないので手間がかかる。

quiz.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

puts "---クイズ---"
puts
puts "以下に出題される問題について、4つの選択肢の中から正しい答えを選び、その番号を入力してください。"
puts

score = 0

puts "[第1問]"
puts "ポーランドの首都は何ですか"
puts "1 ワルシャワ"
puts "2 クラクフ"
puts "3 ポズナン"
puts "4 ピョートルクフ トリブナルス"
print(">>>")
answer = gets.chomp
if answer == "1"
  puts "正解です。"
  score += 1
else
  puts "不正解です。"
end
puts

puts "[第2問]"
puts "ポーランドの公用語は何ですか"
puts "1 英語"
puts "2 ロシア語"
puts "3 ポーランド語"
puts "4 中国語"
print(">>>")
answer = gets.chomp
if answer == "3"
  puts "正解です。"
  score += 1
else
  puts "不正解です。"
end
puts

puts "[第3問]"
puts "ポーランドの海はどれですか"
puts "1 地中海"
puts "2 北海"
puts "3 黒海"
puts "4 バルト海"
print(">>>")
answer = gets.chomp
if answer == "4"
  puts "正解です。"
  score += 1
else
  puts "不正解です。"
end
puts

puts "[第4問]"
puts "ポーランドの国旗の色はどれですか"
puts "1 白,青"
puts "2 青,赤"
puts "3 白,赤"
puts "4 緑,白"
print(">>>")
answer = gets.chomp
if answer == "3"
  puts "正解です。"
  score += 1
else
  puts "不正解です。"
end
puts

puts "[第5問]"
puts "ポーランドの人工は何人ですか"
puts "1 1千200万人"
puts "2 3千800万人"
puts "3 6千500万人"
puts "4 1億1千300万人"
print(">>>")
answer = gets.chomp
if answer == "2"
  puts "正解です。"
  score += 1
else
  puts "不正解です。"
end
puts

puts "修了"
printf("合計得点:%d\n", score)

以下の改善版ではすべてのデータを配列にまとめ、ループの中で配列の要素を順次に取り出して処理を行うという構造になっている。すうすることでプログラムを簡潔にし、コードの無駄な繰り返しを省略できる。

quiz2.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

questions = [
  "ポーランドの首都は何ですか",
  "ポーランドの公用語は何ですか",
  "ポーランドの海はどれですか",
  "ポーランドの国旗の色はどれですか",
  "ポーランドの人工は何人ですか"
]
options = [
  "1 ワルシャワ\n2 クラクフ\n3 ポズナン\n4 ピョートルクフ トリブナルス\n",
  "1 英語\n2 ロシア語\n3 ポーランド語\n4 中国語\n",
  "1 地中海\n2 北海\n3 黒海\n4 バルト海\n",
  "1 白,青\n2 青,赤\n3 白,赤\n4 緑,白\n",
  "1 1千200万人\n2 3千800万人\n3 6千500万人\n4 1億1千300万人\n"
]
correct = [1, 3, 4, 3, 2] # 正解の番号

puts "---クイズ---"
puts
puts "以下に出題される問題について、4つの選択肢の中から正しい答えを選び、その番号を入力してください。"
puts

score = 0
i = 0
for q in questions
  printf("[第%d問]\n", i+1)
  puts q
  puts options[i]
  print(">>>")
  answer = gets.to_i
  if answer == correct[i]
    puts "正解です。"
    score += 1
  else
    puts "不正解です。"
  end
  puts
  i += 1
end

puts "修了"
printf("合計得点:%d\n", score)

しかし、実用的なプログラムではこのようなデータはソースファイルに含めるのではなく、別のファイルで保管するのが一般的である。そうすることによって、データの編集や再利用が容易になる。

データ(特に表データ)を保管するためのフォーマットとして最も広く使われているものの一つとして、CSV (Comma Separated Values) がある。CSVではデータをいくつかのフィールド(項目)に分け、カンマ(,)で区切って記述する。以下の quiz_data.csv は上記のクイズプログラムのデータをCSVに変換したものである。それぞれの行(「レコード」)は一つの質問に関する情報を含む。また、1行目はそれぞれのフィールドの名前を指定する「ヘッダー・レコード」である。フィールドにカンマ、空白文字、ダブルクオート、または改行文字のどれかが含まれているときはダブルクォート("")で括る(下記の例ではそのようなフィールドを異なる文字色で表示している)。

quiz_data.csv
問題,選択肢1,選択肢2,選択肢3,選択肢4,正解
ポーランドの首都は何ですか,ワルシャワ,クラクフ,ポズナン,"ピョートルクフ トリブナルス",1
ポーランドの公用語は何ですか,英語,ロシア語,ポーランド語,中国語,3
ポーランドの海はどれですか,地中海,北海,黒海,バルト海,4
ポーランドの国旗の色はどれですか,"白,青","青,赤","白,赤","緑,白",3
ポーランドの人工は何人ですか,1千200万人,3千800万人,6千500万人,1億1千300万人,2

RubyにはCSVファイルを処理するためのライブラリが用意されているので、CSVデータの操作は簡単である。以下はCSVを用いるクイズプログラムのコードである。

quiz3.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

require 'csv' # csvライブラリを使用可能な状態にする

data = CSV.read("quiz_data.csv", headers: true) # CSVファイルの読み込み

puts "---クイズ---"
puts
puts "以下に出題される問題について、4つの選択肢の中から正しい答えを選び、その番号を入力してください。"
puts

score = 0
i = 0
for record in data
  printf("[第%d問]\n", i+1)
  puts record["問題"]
  print "1 "
  puts record["選択肢1"]
  print "2 "
  puts record["選択肢2"]
  print "3 "
  puts record["選択肢3"]
  print "4 "
  puts record["選択肢4"]
  print(">>>")
  answer = gets.chomp
  if answer == record["正解"]
    puts "正解です。"
    score += 1
  else
    puts "不正解です。"
  end
  puts
  i += 1
end

puts "修了"
printf("合計得点:%d\n", score)

解説:先ずは CSV.read を用いてファイルから全データを読み込んで data という変数に記憶させる。それから、for ループを使って各行(レコード)に含まれているデータを順番に取り出して record に代入する。また、今回のレコードから特定のフィールドに入っている内容を抽出する時は record["選択肢1"] のように、1行目で指定されたフィールドの名前を使う。


本日の課題

各グループの代表者1名がこれまでの進捗状況を報告すること。


目次