OOP版はこちら↓
【Ruby3.1】ボウリングのスコア計算プログラムをオブジェクト指向で作る - あまブログ
1. 実行環境 macOS Monterey 12.4 Ruby 3.1.0 2. ボウリングのスコア計算プログラムの要件 1ゲーム = 10フレーム 1フレーム = 2投 スペアのフレームの得点は次の1投の点を加算する。 ストライクのフレームの得点は次の2投の点を加算する。 10フレーム目は1投目がストライクもしくは2投目がスペアだった場合、3投目が投げられる。 ありえない投球数やありえない数字・記号がこない前提。 入力例:6,3,9,0,0,3,8,2,7,3,X,9,1,8,0,X,6,4,5 3. ソースコード ver1:自作→レビュー反映 ver2:ver1→他の人のコードを反映 3-1. ver1 #!/usr/bin/env ruby # frozen_string_literal: true score = ARGV[0] scores = score.split(',') shots = [] scores.each do |s| if s == 'X' shots << 10 shots << 0 else shots << s.to_i end end frames = [] shots.each_slice(2) do |s| frames << s end frames_point = [] frames.each_with_index do |frame, i| frames_point[i] = frame.sum if i < 9 if frame[0] == 10 frames_point[i] += frames[i + 1][0] frames_point[i] += if frames[i + 1][0] == 10 frames[i + 2][0] else frames[i + 1][1] end elsif frame.sum == 10 frames_point[i] += frames[i + 1][0] end end end puts frames_point.sum 3-2. ver2 #!/usr/bin/env ruby # frozen_string_literal: true shots = ARGV[0].split(',').map { |s| s == 'X' ? 10 : s.to_i } frame = [] frames = [] shots.each do |s| frame << s if frames.length < 10 if frame.length >= 2 || s == 10 frames << frame.dup frame.clear end else frames.last << s end end point = 0 (0..9).each do |n| point += frames[n].sum frames[n + 1] ||= [] frames[n + 2] ||= [] if frames[n][0] == 10 point += (frames[n + 1] + frames[n + 2]).slice(0, 2).sum elsif frames[n].sum == 10 point += frames[n + 1][0] end end puts point 4. ソースコード(ver2)の解説 4-1. 主な使用メソッド String#split Enumerable#map Array#length Array#dup Array#clear Array#last Array#slice Array#sum 4-2. 解説 4行目 shots = ARGV[0].split(',').map { |s| s == 'X' ? 10 : s.to_i } ARGV[0].split(',')で入力された文字列を,で分割して文字列の配列にする "6,3,9,0,0,3,8,2,7,3,X,9,1,8,0,X,6,4,5"が["6", "3", "9", "0", "0", "3", "8", "2", "7", "3", "X", "9", "1", "8", "0", "X", "6", "4", "5"]になる .map { |s| s == 'X' ? 10 : s.to_i }でXを数値の10に、それ以外を数値に変換する 結果、shotsには[6, 3, 9, 0, 0, 3, 8, 2, 7, 3, 10, 9, 1, 8, 0, 10, 6, 4, 5]が入る 6~18行目 frame = [] frames = [] shots.each do |s| frame << s if frames.length < 10 if frame.length >= 2 || s == 10 # frameに2投またはストライクの1投が入ったら frames << frame.dup frame.clear end else # 10フレーム目 frames.last << s end end shots[6, 3, 9, 0, 0, 3, 8, 2, 7, 3, 10, 9, 1, 8, 0, 10, 6, 4, 5]から、各フレーム毎に分割したframes[[6, 3], [9, 0], [0, 3], [8, 2], [7, 3], [10], [9, 1], [8, 0], [10], [6, 4, 5]]を作りたい
...