おーしまブログ

プログラミングやってます

<Ruby>BINGOのプログラム作ってみた

こんにちは、おーしまです。

今回はRubyで「ビンゴプログラム」を作ってみました。


<概要>

⑴最初に、5x5のビンゴカードに1~50の数字をランダムに振り分け、真ん中に穴を開ける。
f:id:tomo_bb_aki0118115:20201004230003p:plain
⑵エンターキーを押すたびに、1~50のランダムな数字を決め、ビンゴカードに同じ数字があると、穴を開ける。
f:id:tomo_bb_aki0118115:20201004230147p:plain
⑶同じ数字がない場合は「(数字)はありません」と表示
f:id:tomo_bb_aki0118115:20201004230325p:plain
⑷縦、横、斜めのいずれかで真っ直ぐに穴が開くと「BINGO!」と表示して終了
f:id:tomo_bb_aki0118115:20201004230434p:plain




一つもメソッドを作らず、何回も同じコードを書いているカスみたいなプログラムですが、
あまりネットを見ずに自分なりに頑張って作ってみました。(下に解説も書きます)


bingo_card = ["B","I","N","G","O"]
random_num =[]
50.times do |p|
  random_num << p + 1
end

#カードを作る
5.times do |j|
  line = []
  num = 0
  5.times do |i|
    num = random_num.sample
    random_num.delete(num)
    if num < 10
      num = " #{num}"
    end
    line << " #{num} "
  end
  bingo_card[j] = line
end 

#真ん中に穴を開け、ビンゴカードを表示
kaiten = gets
bingo_card[2][2] = " ⬛️ "
bingo_card.each do |bingocard|
  puts bingocard.join
end

#ランダムで数字を出し揃うと穴を開ける、揃ったら終わり
flag = 0
holl_count = 1
50.times do |p|
  random_num << p + 1
end
while flag == 0 do
  kaiten = gets
  number = random_num.sample
  random_num.delete(number)
  if number < 10
    number = " #{number}"
  end
  s = 0
  bingo_card.each do |line|
    q = 0
    line.each do |masu|
      if " #{number} " == masu
        bingo_card[s][q] = " ⬛️ " 
        bingo_card.each do |bingocard|
          puts bingocard.join
        end
      end
      q += 1
    end
    s += 1
  end
  bingo_card_holl_count = 0
  bingo_card.each do |line|
    bingo_card_holl_count += line.count(" ⬛️ ")
  end
  if  holl_count == bingo_card_holl_count
    puts "#{number}はありません"
  else
    holl_count += 1
    puts "#{number}はありました!!!!!!!!!!"
  end
  miginanamecheck = []
  hidarinanamecheck =[]
  5.times do |yoko|
    yokocheck = []
    tatecheck = []
    5.times do |tate|
      yokocheck << bingo_card[yoko][tate]
      tatecheck << bingo_card[tate][yoko]
      if yoko == tate
        miginanamecheck << bingo_card[yoko][tate]
      end
      if (yoko + tate) == 4
        hidarinanamecheck << bingo_card[yoko][tate]
      end
    end
    if yokocheck.count(" ⬛️ ") == 5
      puts "BINGO!!!!!"
      flag = 1
    elsif tatecheck.count(" ⬛️ ") == 5
      puts "BINGO!!!!!"
      flag = 1
    end
  end
  if miginanamecheck.count(" ⬛️ ") == 5
    puts "BINGO!!!!!"
    flag = 1
  elsif hidarinanamecheck.count(" ⬛️ ") == 5
    puts "BINGO!!!!!"
    flag =1
  end
end

puts "!!!!!!!!!おめでとう!!!!!!!!!!!!!"

解説

1.

bingo_card = ["B","I","N","G","O"]
random_num =[]
50.times do |p|
  random_num << p + 1
end

まず、ビンゴカードの配列と、1~50の数字が入った配列を用意しています。

2.

5.times do |j|
  line = []
  num = 0
  5.times do |i|
    num = random_num.sample
    random_num.delete(num)
    if num < 10
      num = " #{num}"
    end
    line << " #{num} "
  end
  bingo_card[j] = line
end 

次に、timesメソッドを入れ子構造にして、
line に random_num からランダムに数字を取り出して入れます。
ランダムに数字を取り出すときは、sampleメソッドを使用し、
一度使った数字がもう一度出ないように、deleteメソッドで使った数字を配列内から削除しています。
綺麗な5x5に見せるため、数字が一桁の時は、半角スペースを足しています。
line の中に数字が5個入ると、bingo_card に line を入れ、それを5回繰り返すことで5x5を作っています。

3.

#真ん中に穴を開け、ビンゴカードを表示
kaiten = gets
bingo_card[2][2] = " ⬛️ "
bingo_card.each do |bingocard|
  puts bingocard.join
end

getsメソッドを使って、エンターキーを押すと次に進むようにしています。
kaiten に意味はありません。
[2][2] で真ん中を指定し、穴(⬛️)を開け、
eachメソッドと、joinメソッドを用いて、配列を並べて表示しています。

4.

#ランダムで数字を出し揃うと穴を開ける、揃ったら終わり

flag = 0
holl_count = 1
50.times do |p|
  random_num << p + 1
end
while flag == 0 do
  kaiten = gets
  number = random_num.sample
  random_num.delete(number)
  if number < 10
    number = " #{number}"
  end
  s = 0
  bingo_card.each do |line|
    q = 0
    line.each do |masu|
      if " #{number} " == masu
        bingo_card[s][q] = " ⬛️ " 
        bingo_card.each do |bingocard|
          puts bingocard.join
        end
      end
      q += 1
    end
    s += 1
  end
  bingo_card_holl_count = 0
  bingo_card.each do |line|
    bingo_card_holl_count += line.count(" ⬛️ ")
  end
  if  holl_count == bingo_card_holl_count
    puts "#{number}はありません"
  else
    holl_count += 1
    puts "#{number}はありました!!!!!!!!!!"
  end
  miginanamecheck = []
  hidarinanamecheck =[]
  5.times do |yoko|
    yokocheck = []
    tatecheck = []
    5.times do |tate|
      yokocheck << bingo_card[yoko][tate]
      tatecheck << bingo_card[tate][yoko]
      if yoko == tate
        miginanamecheck << bingo_card[yoko][tate]
      end
      if (yoko + tate) == 4
        hidarinanamecheck << bingo_card[yoko][tate]
      end
    end
    if yokocheck.count(" ⬛️ ") == 5
      puts "BINGO!!!!!"
      flag = 1
    elsif tatecheck.count(" ⬛️ ") == 5
      puts "BINGO!!!!!"
      flag = 1
    end
  end
  if miginanamecheck.count(" ⬛️ ") == 5
    puts "BINGO!!!!!"
    flag = 1
  elsif hidarinanamecheck.count(" ⬛️ ") == 5
    puts "BINGO!!!!!"
    flag =1
  end
end

puts "!!!!!!!!!おめでとう!!!!!!!!!!!!!"
flag = 0
holl_count = 1
50.times do |p|
  random_num << p + 1
end

flag は while 文の条件式で使います。
holl_count は毎回穴が開いたか開いてないか調べるときに使います。
random_num に1~50の数字を入れます。(同じコードを二回記述する愚行)

while flag == 0 do
  kaiten = gets
  number = random_num.sample
  random_num.delete(number)
  if number < 10
    number = " #{number}"
  end
  s = 0
  bingo_card.each do |line|
    q = 0
    line.each do |masu|
      if " #{number} " == masu
        bingo_card[s][q] = " ⬛️ " 
        bingo_card.each do |bingocard|
          puts bingocard.join
        end
      end
      q += 1
    end
    s += 1
  end

while文で flag が0の限り続けます。(BINGOしたらflag を1にするようにする)
前と同じように、number にランダムで数字を入れ、その数字を削除します。
一桁の数字は半角スペースを入れます。
s と q の変数を作り、eachメソッドを使って、同じ数字がないか見ていきます。
繰り返すたびにsとqの値が1ずつ増えるので、binngo_card[s][q]としておけば、
数字が同じだったときの場所に、⬛️を代入することができます。
加えて、ビンゴカードの表示もします。

bingo_card_holl_count = 0
  bingo_card.each do |line|
    bingo_card_holl_count += line.count(" ⬛️ ")
  end
  if  holl_count == bingo_card_holl_count
    puts "#{number}はありません"
  else
    holl_count += 1
    puts "#{number}はありました!!!!!!!!!!"
  end

bingo_card_holl_count に countメソッドを使って穴の数を代入します。(変数の命名下手すぎる笑)
(lineごとに⬛️があった数だけbingo_card_holl_countに足している。)
holl_count(前回の穴の数)とbingo_card_holl_count(ビンゴカードに開いている穴の数)を比べて、
同じであれば「ありません」
それ以外は「ありました」と表示し、holl_count に1を足して
holl_countとbingo_card_holl_countが同じ数になるようにして、次に進みます。

  miginanamecheck = []
  hidarinanamecheck =[]
  5.times do |yoko|
    yokocheck = []
    tatecheck = []
    5.times do |tate|
      yokocheck << bingo_card[yoko][tate]
      tatecheck << bingo_card[tate][yoko]
      if yoko == tate
        miginanamecheck << bingo_card[yoko][tate]
      end
      if (yoko + tate) == 4
        hidarinanamecheck << bingo_card[yoko][tate]
      end
    end
    if yokocheck.count(" ⬛️ ") == 5
      puts "BINGO!!!!!"
      flag = 1
    elsif tatecheck.count(" ⬛️ ") == 5
      puts "BINGO!!!!!"
      flag = 1
    end
  end
  if miginanamecheck.count(" ⬛️ ") == 5
    puts "BINGO!!!!!"
    flag = 1
  elsif hidarinanamecheck.count(" ⬛️ ") == 5
    puts "BINGO!!!!!"
    flag =1
  end
end

puts "!!!!!!!!!おめでとう!!!!!!!!!!!!!"

縦、横、斜めで⬛️が揃っていないか調べます。
miginanamecheck =
hidarinanamecheck =

yokocheck =
tatecheck =

の4つの配列を作り、timesメソッドを用いて、
bingo_card[yoko][tate]とすることで、上から順に横一列の数字をyokocheckに入れていき、
bingo_card[tate][yoko]とすることで、左から順に縦一列の数字をtatecheckに入れていきます。

右斜めは、配列の添え字が[0][0]、[1][1]、[2][2]、[3][3]、[4][4]、となることから
yoko == tate の時、miginanamecheck に数字を入れていきます。
左斜めは、配列の添え字が[0][4]、[1][3]、[2][2]、[3][1]、[4][0]、となることから
(yoko + tate) == 4 の時、hidarinanamecheck に数字を入れていきます。

これで、どれかのcheck配列の中身に5個の⬛️が入っていればBINGOとなるため、
if と elsif で調べ、⬛️が5個あれば、"BINGO"と表示させ、flag = 1 として、繰り返しを終わらせます。

感想

めっちゃ大変でした。
コードが長すぎるし、変数名が適当で見にくいですが、なんとか自分の力で完成させることができたので、よかったです。
自分で何かプログラムを作ってみることで、調べる力や、問題を解決する力、構造的にコードを書いていく力が定着していくとわかったので、もっといろんなアプリケーションを作っていきたいと思いました。
後日、ネットでビンゴのプログラムを探して、自分のものとどこが違うのか復習していきます。


今回はここまでです。
それでは、また〜

ここはどこ おれはだれ それに近いものがあんだよ 始めようとした奴らも迷い始めてる 怖がらせないでよ そりゃ甘くはないけど まだまだ 夢見ていい世界なんでしょ {UVERwould「ハイ!問題作」}