Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 21133

【超初心者用】RubyでBINGOカードを作る手順を丁寧すぎるぐらいに書いてみた(2)

$
0
0

はじめに

 B |  I |  N |  G |  O
 8 | 16 | 36 | 57 | 67
10 | 24 | 33 | 58 | 72
 2 | 17 |    | 51 | 69
 7 | 18 | 45 | 59 | 62
 4 | 21 | 37 | 53 | 71

今回は(2)で前回の記事に続き、CodeIQに「ビンゴカード作成問題」を出題しました。みなさんの挑戦をお待ちしてます!を参考にRubyでBINGOカードを作るを作ってみようと思いました。

しかしですね、インプットしかしてなかった人にはBINGOカードと言えど、これをアウトプットするのは多少なりとも苦戦するのではないでしょうか?

今回は、自分なりに順を追ってどのように作成していったかを記載していきます。
本当に、超初心者用にめちゃくちゃ丁寧に手順を記しています。

『そんな基本的な事・・・』と思わずみていただけると幸いです(笑)

そして何よりも、手順も考え方も無茶苦茶ではあると思います。

試行錯誤ある中で学習していきます。

ちなみに(1)の【超初心者用】RubyでBINGOカードを作る手順を丁寧すぎるぐらいに書いてみた(1)が最初です。

作成手順にもっと効率の良い方法などありましたら、是非意見をお待ちしております。

前回の時点

 B |  I |  N |  G |  O
14 | 30 | 35 | 55 | 64
6 | 23 | 41 | 50 | 71
9 | 19 | 45 | 59 | 74
4 | 24 | 37 | 52 | 70
8 | 22 | 31 | 48 | 68

ランダムな数字をカード形式に作り上げるところまでいきました。

まだ、していない事は

・カード真ん中の空欄を開ける
Bの列の|の位置を揃える
・全力のリファクタリング

です。

それでは、実装していきます。

カード真ん中の空欄を開ける

ここでは、string[]を使います。

[]内で文字の場所を指定します。

今回は、列、行、共に3番目の位置。つまり、インデックス番号でいう2が真ん中なので。

bingo.rb
bingos[2][2]="  "

とします。

bingo.rb
defnumbersbingos=[B,I,N,G,O].map{|bingo|bingo.sample(5)}.transposebingos[2][2]="  "bingos.map{|bin|bin.join(" | ")}.join("\n")endputsnumbers
 B |  I |  N |  G |  O
2 | 26 | 38 | 58 | 63
5 | 20 | 35 | 59 | 64
15 | 19 |    | 56 | 71
1 | 23 | 43 | 52 | 62
11 | 30 | 34 | 50 | 70

何とか真ん中を開けることは出来ました。

後は、|の位置を揃えてあげるだけですね。

列の|の位置を揃える

ポイントは、BINGOという文字列とランダムな数字を右詰めにする事です。

しかし、しかし無理やり" "で空白を作ろうにも1桁の数字と2桁の数字が混在しているので上手くいきません。

右詰めにするメソッドがあれば・・・

と思っていたらありました。(笑)

文字列.rjustを使ってあげます。
これは、右詰めにした文字列を返すメソッドです。

これで完成まで出来そうですね。

と思ったのですが、、、

bingo.rb
defnumbersbingos=[B,I,N,G,O].map{|bingo|bingo.sample(5)}.transposebingos[2][2]="  "bingos.map{|bin|bin.join(" | ").to_s.rjust(2)#.to_s.rjust(2)追加}.join("\n")endputsnumbers
 B |  I |  N |  G |  O
11 | 28 | 33 | 56 | 66
7 | 27 | 32 | 55 | 61
4 | 25 |    | 59 | 63
6 | 24 | 37 | 51 | 71
15 | 22 | 39 | 58 | 72

変わりません。

原因を考えてみます。

おそらく、rjustメソッドは文字列に対して使うメソッドですから、これが効いていないとなると。
今回使っている場所は文字列に対してではない?のかと思われます。to_sで文字列に変更しているつもりだったのですが。。。(分かる方、教えてください。)

やり方を変えてみます。

どんっ

bingo.rb
defnumbersbingos=[B,I,N,G,O].map{|bingo|bingo.sample(5)}.transposebingos[2][2]="  "bingos.map{|bin|bin.map{|b|b.to_s.rjust(2)}.join(" | ")}.join("\n")end
 B |  I |  N |  G |  O
 8 | 16 | 36 | 57 | 67
10 | 24 | 33 | 58 | 72
 2 | 17 |    | 51 | 69
 7 | 18 | 45 | 59 | 62
 4 | 21 | 37 | 53 | 71

bingos.mapの中にもう一つmapメソッドを足してjointo_s.rjust(2)を分けてみました。

原因は、joinメソッドが右詰めの邪魔をしていたのではないか?と思っています。

何とか、これでやっと完成ですね!!!

bingo.rb
B=(1..15).to_aI=(16..30).to_aN=(31..45).to_aG=(46..60).to_aO=(61..75).to_adefword[' B',' I',' N',' G',' O'].join(' | ')enddefnumbersbingos=[B,I,N,G,O].map{|bingo|bingo.sample(5)}.transposebingos[2][2]="  "bingos.map{|bin|bin.map{|b|b.to_s.rjust(2)}.join(" | ")}.join("\n")endputswordputsnumbers

これが現時点でのソースコードですが、

まだまだ、リファクタリングのしがいがありそうです。

リファクタリングしていく

まずは、

bingo.rb
B=(1..15).to_aI=(16..30).to_aN=(31..45).to_aG=(46..60).to_aO=(61..75).to_a

の部分ですね。
まとめていきます。

この変数たちは、『15個の数字の配列』を示しているわけですから。
何か良い方法でまとめられそうです。

each_sliceメソッドを使う

each_sliceメソッドは配列を分割するのに使うメソッドです。

これを上手く使っていきます。

bingo.rb
B=(1..15).to_aI=(16..30).to_aN=(31..45).to_aG=(46..60).to_aO=(61..75).to_abingos=[B,I,N,G,O].map{|bingo|bingo.sample(5)}.transpose

こちらが現時点のコード。これをeach_sliceメソッドを使って変更していく。

これが何とも見事。

bingo.rb
bingos=(1..75).each_slice(15).map{|bingo|bingo.sample(5)}.transpose

6行から1行へとこんなにも短くなりました!

空白+文字列(' '+文字列)で作った見た目の悪い配列をどうにかする

bingo.rb
defword[' B',' I',' N',' G',' O'].join(' | ')end

これですね。' B'では、空白+文字列で無理やり文字を作りました。
どうにかしていきます。

charsメソッドを使います

これは、文字列の文字を一文字ずつ配列へと返すメソッドです。

sample.rb
"banana".chars#=> ["b", "a", "n", "a", "n", "a"]

これを使います。

bingo.rb
["BINGO".chars]#[' B', ' I', ' N', ' G', ' O']を変更

ですが、これでは空白がなくなってしまいましたね。

このまま出力すると

B | I | N | G | O
11 | 24 | 40 | 53 | 73
 5 | 21 | 33 | 52 | 70
10 | 28 |    | 46 | 75
12 | 20 | 38 | 48 | 71
 1 | 26 | 42 | 56 | 63

空白をどうにかしましょう。

ここでもう一度、ここまでで使ったメソッドを思い出してみます。

文字数を調節するメソッドがありました。右詰めにするヤツ。

そうです。

rjustメソッドです

ちなみに現在のコードは

bingo.rb
defword["BINGO".chars].join(' | ')enddefnumbersbingos=(1..75).each_slice(15).map{|bingo|bingo.sample(5)}.transposebingos[2][2]="  "bingos.map{|bin|bin.map{|b|b.to_s.rjust(2)}.join(" | ")}.join("\n")endputswordputsnumbers

rjustメソッドは一度使っているのでその位置にまとめることが出来そうですね。

やってみましょう。

仕上げにかかります

まずは、def worddef numbersをまとめます。

そして、変数の名前も分かりやすいように変更していきます。

出来たものがこちら。

bingo.rb
defbingowords=["BINGO".chars]numbers=(1..75).each_slice(15).map{|number|number.sample(5)}.transposenumbers[2][2]="  "cards=words+numberscards.map{|card|card.map{|c|c.to_s.rjust(2)}.join(" | ")}.join("\n")endputsbingo
 B |  I |  N |  G |  O
 3 | 19 | 39 | 46 | 69
 8 | 21 | 35 | 50 | 61
13 | 22 |    | 58 | 68
10 | 16 | 44 | 55 | 74
 1 | 28 | 40 | 56 | 66

完成です。お疲れ様でした。


Viewing all articles
Browse latest Browse all 21133

Trending Articles